<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>ebook | 房飞跃的博客</title>
    <meta name="generator" content="VuePress 1.8.2">
    <link rel="apple-touch-icon" href="/apple-touch-icon.png">
    <link rel="icon" href="/favicon.ico">
    <link rel="manifest" href="/manifest.json">
    <meta name="description" content="房飞跃的博客">
    <meta name="theme-color" content="#ffffff">
    
    <link rel="preload" href="/assets/css/0.styles.e57fdc06.css" as="style"><link rel="preload" href="/assets/js/app.8c5a7a92.js" as="script"><link rel="preload" href="/assets/js/2.8e30e130.js" as="script"><link rel="preload" href="/assets/js/10.e695640a.js" as="script"><link rel="preload" href="/assets/js/64.0323ed89.js" as="script"><link rel="prefetch" href="/assets/js/100.fae9757f.js"><link rel="prefetch" href="/assets/js/101.d26f7a9a.js"><link rel="prefetch" href="/assets/js/102.e9b20f43.js"><link rel="prefetch" href="/assets/js/103.6d251ff3.js"><link rel="prefetch" href="/assets/js/104.5de918be.js"><link rel="prefetch" href="/assets/js/105.aead61a1.js"><link rel="prefetch" href="/assets/js/106.09a5decb.js"><link rel="prefetch" href="/assets/js/107.a44fc48a.js"><link rel="prefetch" href="/assets/js/108.cec63522.js"><link rel="prefetch" href="/assets/js/109.db1a4ed7.js"><link rel="prefetch" href="/assets/js/11.769ac82c.js"><link rel="prefetch" href="/assets/js/110.10914d38.js"><link rel="prefetch" href="/assets/js/111.2c0ddf25.js"><link rel="prefetch" href="/assets/js/112.c792ca07.js"><link rel="prefetch" href="/assets/js/113.a769ad8f.js"><link rel="prefetch" href="/assets/js/114.c1dca6a0.js"><link rel="prefetch" href="/assets/js/115.82e1fb4f.js"><link rel="prefetch" href="/assets/js/116.c927762b.js"><link rel="prefetch" href="/assets/js/117.5c14eedf.js"><link rel="prefetch" href="/assets/js/118.24861bb6.js"><link rel="prefetch" href="/assets/js/119.3fafaebf.js"><link rel="prefetch" href="/assets/js/12.23031504.js"><link rel="prefetch" href="/assets/js/120.a9ff8fae.js"><link rel="prefetch" href="/assets/js/121.3eb4b3a1.js"><link rel="prefetch" href="/assets/js/122.ff06cffe.js"><link rel="prefetch" href="/assets/js/123.aaf767a6.js"><link rel="prefetch" href="/assets/js/124.4daf257a.js"><link rel="prefetch" href="/assets/js/125.e7e71d3f.js"><link rel="prefetch" href="/assets/js/126.cdee6d86.js"><link rel="prefetch" href="/assets/js/127.aa133c3f.js"><link rel="prefetch" href="/assets/js/128.a8e7d8b2.js"><link rel="prefetch" href="/assets/js/129.dcca2d84.js"><link rel="prefetch" href="/assets/js/13.f37f647e.js"><link rel="prefetch" href="/assets/js/130.3925fb20.js"><link rel="prefetch" href="/assets/js/131.a3a759ed.js"><link rel="prefetch" href="/assets/js/132.84bb9bf9.js"><link rel="prefetch" href="/assets/js/133.30fceda7.js"><link rel="prefetch" href="/assets/js/134.e02f66bf.js"><link rel="prefetch" href="/assets/js/135.71a35d7f.js"><link rel="prefetch" href="/assets/js/136.77762773.js"><link rel="prefetch" href="/assets/js/137.b9741de3.js"><link rel="prefetch" href="/assets/js/138.59b64aa0.js"><link rel="prefetch" href="/assets/js/139.d81e68a1.js"><link rel="prefetch" href="/assets/js/14.0091824d.js"><link rel="prefetch" href="/assets/js/140.68388ddb.js"><link rel="prefetch" href="/assets/js/141.e69cc877.js"><link rel="prefetch" href="/assets/js/142.65fc1806.js"><link rel="prefetch" href="/assets/js/143.4f1e9b3d.js"><link rel="prefetch" href="/assets/js/144.5cf4bdda.js"><link rel="prefetch" href="/assets/js/145.1a1cdb18.js"><link rel="prefetch" href="/assets/js/146.ef4fe2c3.js"><link rel="prefetch" href="/assets/js/147.f5e5d206.js"><link rel="prefetch" href="/assets/js/148.07c7208f.js"><link rel="prefetch" href="/assets/js/149.fb71df8d.js"><link rel="prefetch" href="/assets/js/15.4e1991f3.js"><link rel="prefetch" href="/assets/js/150.771bcbfe.js"><link rel="prefetch" href="/assets/js/151.de02cd55.js"><link rel="prefetch" href="/assets/js/152.6a5b243d.js"><link rel="prefetch" href="/assets/js/153.c1c426d2.js"><link rel="prefetch" href="/assets/js/154.51e08a99.js"><link rel="prefetch" href="/assets/js/155.ab801c7a.js"><link rel="prefetch" href="/assets/js/156.e62111f0.js"><link rel="prefetch" href="/assets/js/157.67f19eb7.js"><link rel="prefetch" href="/assets/js/158.3e57553c.js"><link rel="prefetch" href="/assets/js/159.f01ea56a.js"><link rel="prefetch" href="/assets/js/16.aafe549d.js"><link rel="prefetch" href="/assets/js/160.81468500.js"><link rel="prefetch" href="/assets/js/161.8341c4c9.js"><link rel="prefetch" href="/assets/js/162.18cd1d1e.js"><link rel="prefetch" href="/assets/js/163.2ed65e27.js"><link rel="prefetch" href="/assets/js/164.1c0adbfd.js"><link rel="prefetch" href="/assets/js/165.4382f96e.js"><link rel="prefetch" href="/assets/js/166.47ad10ec.js"><link rel="prefetch" href="/assets/js/167.ee3e3de3.js"><link rel="prefetch" href="/assets/js/168.1273ebb0.js"><link rel="prefetch" href="/assets/js/169.bb6578e0.js"><link rel="prefetch" href="/assets/js/17.4548c40c.js"><link rel="prefetch" href="/assets/js/170.6aef0437.js"><link rel="prefetch" href="/assets/js/171.4818ad12.js"><link rel="prefetch" href="/assets/js/172.7f4674ed.js"><link rel="prefetch" href="/assets/js/173.25951cfa.js"><link rel="prefetch" href="/assets/js/174.604b8889.js"><link rel="prefetch" href="/assets/js/175.752d6221.js"><link rel="prefetch" href="/assets/js/176.ee6ccaf2.js"><link rel="prefetch" href="/assets/js/177.df3e7548.js"><link rel="prefetch" href="/assets/js/178.0c05bdea.js"><link rel="prefetch" href="/assets/js/179.fa300396.js"><link rel="prefetch" href="/assets/js/18.4a166581.js"><link rel="prefetch" href="/assets/js/180.78580e5a.js"><link rel="prefetch" href="/assets/js/181.c08c58e9.js"><link rel="prefetch" href="/assets/js/182.425fd44a.js"><link rel="prefetch" href="/assets/js/183.643e0376.js"><link rel="prefetch" href="/assets/js/184.28243fe4.js"><link rel="prefetch" href="/assets/js/185.145fafb0.js"><link rel="prefetch" href="/assets/js/186.9c005fb8.js"><link rel="prefetch" href="/assets/js/187.a1c8a8da.js"><link rel="prefetch" href="/assets/js/188.b78deff0.js"><link rel="prefetch" href="/assets/js/189.86432945.js"><link rel="prefetch" href="/assets/js/19.992da7e4.js"><link rel="prefetch" href="/assets/js/190.b6c616c9.js"><link rel="prefetch" href="/assets/js/191.d2a4a045.js"><link rel="prefetch" href="/assets/js/192.ce93c157.js"><link rel="prefetch" href="/assets/js/193.f45b56e8.js"><link rel="prefetch" href="/assets/js/194.60166b01.js"><link rel="prefetch" href="/assets/js/195.fea0fdcc.js"><link rel="prefetch" href="/assets/js/196.7f9353e4.js"><link rel="prefetch" href="/assets/js/197.2a8de731.js"><link rel="prefetch" href="/assets/js/198.6f3d807b.js"><link rel="prefetch" href="/assets/js/199.75028922.js"><link rel="prefetch" href="/assets/js/20.e27836ed.js"><link rel="prefetch" href="/assets/js/200.36fbe8e0.js"><link rel="prefetch" href="/assets/js/201.ca3a3d7d.js"><link rel="prefetch" href="/assets/js/202.8cc508cd.js"><link rel="prefetch" href="/assets/js/203.eb6662a4.js"><link rel="prefetch" href="/assets/js/204.a75edc0d.js"><link rel="prefetch" href="/assets/js/205.77cc7661.js"><link rel="prefetch" href="/assets/js/206.7cfc88ae.js"><link rel="prefetch" href="/assets/js/207.9d5b5377.js"><link rel="prefetch" href="/assets/js/208.9308a3b3.js"><link rel="prefetch" href="/assets/js/209.cbee10e7.js"><link rel="prefetch" href="/assets/js/21.9bc4424f.js"><link rel="prefetch" href="/assets/js/210.3dbd53b3.js"><link rel="prefetch" href="/assets/js/211.ffc0051e.js"><link rel="prefetch" href="/assets/js/212.420b9a23.js"><link rel="prefetch" href="/assets/js/213.da84f0aa.js"><link rel="prefetch" href="/assets/js/214.2a5308ff.js"><link rel="prefetch" href="/assets/js/215.bc87143e.js"><link rel="prefetch" href="/assets/js/216.f099b04d.js"><link rel="prefetch" href="/assets/js/217.39cc059e.js"><link rel="prefetch" href="/assets/js/218.3b588871.js"><link rel="prefetch" href="/assets/js/219.8c7c7f40.js"><link rel="prefetch" href="/assets/js/22.287b20ef.js"><link rel="prefetch" href="/assets/js/220.6a490188.js"><link rel="prefetch" href="/assets/js/221.a06fe7b9.js"><link rel="prefetch" href="/assets/js/222.0da34a82.js"><link rel="prefetch" href="/assets/js/223.6d6abad9.js"><link rel="prefetch" href="/assets/js/224.de157359.js"><link rel="prefetch" href="/assets/js/225.c733d3d1.js"><link rel="prefetch" href="/assets/js/226.039d453b.js"><link rel="prefetch" href="/assets/js/227.dbe84815.js"><link rel="prefetch" href="/assets/js/228.4850e3f3.js"><link rel="prefetch" href="/assets/js/229.322215a9.js"><link rel="prefetch" href="/assets/js/23.c1fc6d56.js"><link rel="prefetch" href="/assets/js/230.2469fb45.js"><link rel="prefetch" href="/assets/js/231.a77224ae.js"><link rel="prefetch" href="/assets/js/232.56534eb1.js"><link rel="prefetch" href="/assets/js/233.f69b682d.js"><link rel="prefetch" href="/assets/js/234.33fecaf9.js"><link rel="prefetch" href="/assets/js/235.3152a6d8.js"><link rel="prefetch" href="/assets/js/236.4a45a619.js"><link rel="prefetch" href="/assets/js/237.683796c5.js"><link rel="prefetch" href="/assets/js/238.4183baab.js"><link rel="prefetch" href="/assets/js/239.967342f3.js"><link rel="prefetch" href="/assets/js/24.c4266153.js"><link rel="prefetch" href="/assets/js/240.4ebdaa3e.js"><link rel="prefetch" href="/assets/js/241.3853f81e.js"><link rel="prefetch" href="/assets/js/242.0be00241.js"><link rel="prefetch" href="/assets/js/243.27a16565.js"><link rel="prefetch" href="/assets/js/244.4b6c0842.js"><link rel="prefetch" href="/assets/js/245.0ff5b09e.js"><link rel="prefetch" href="/assets/js/246.ec9708bc.js"><link rel="prefetch" href="/assets/js/247.33dd2e3f.js"><link rel="prefetch" href="/assets/js/248.e095c83d.js"><link rel="prefetch" href="/assets/js/249.e35dae0b.js"><link rel="prefetch" href="/assets/js/25.0bd19957.js"><link rel="prefetch" href="/assets/js/250.b7dda30b.js"><link rel="prefetch" href="/assets/js/251.373c219f.js"><link rel="prefetch" href="/assets/js/252.f02d8652.js"><link rel="prefetch" href="/assets/js/253.0129ab3b.js"><link rel="prefetch" href="/assets/js/254.05bc87ae.js"><link rel="prefetch" href="/assets/js/255.93959060.js"><link rel="prefetch" href="/assets/js/256.036268bb.js"><link rel="prefetch" href="/assets/js/257.4cfe4c46.js"><link rel="prefetch" href="/assets/js/258.70f49e1e.js"><link rel="prefetch" href="/assets/js/259.e92d7a7e.js"><link rel="prefetch" href="/assets/js/26.cd8cc5bc.js"><link rel="prefetch" href="/assets/js/260.24ecb139.js"><link rel="prefetch" href="/assets/js/261.32f0c433.js"><link rel="prefetch" href="/assets/js/262.aca4b5e9.js"><link rel="prefetch" href="/assets/js/263.0051554a.js"><link rel="prefetch" href="/assets/js/264.063d3092.js"><link rel="prefetch" href="/assets/js/265.de1fe60c.js"><link rel="prefetch" href="/assets/js/266.4407a594.js"><link rel="prefetch" href="/assets/js/267.9318dca9.js"><link rel="prefetch" href="/assets/js/268.b9696b4c.js"><link rel="prefetch" href="/assets/js/269.21743bc6.js"><link rel="prefetch" href="/assets/js/27.e0c9a2d1.js"><link rel="prefetch" href="/assets/js/270.64175904.js"><link rel="prefetch" href="/assets/js/271.ab988e51.js"><link rel="prefetch" href="/assets/js/272.40190656.js"><link rel="prefetch" href="/assets/js/273.124f97d6.js"><link rel="prefetch" href="/assets/js/274.ac2ae949.js"><link rel="prefetch" href="/assets/js/275.84112c31.js"><link rel="prefetch" href="/assets/js/276.5cd3a2f1.js"><link rel="prefetch" href="/assets/js/277.dfd266d2.js"><link rel="prefetch" href="/assets/js/278.2c22b507.js"><link rel="prefetch" href="/assets/js/279.143630b9.js"><link rel="prefetch" href="/assets/js/28.ee8b098b.js"><link rel="prefetch" href="/assets/js/280.e52e72d5.js"><link rel="prefetch" href="/assets/js/281.fa255716.js"><link rel="prefetch" href="/assets/js/282.33cf3680.js"><link rel="prefetch" href="/assets/js/283.8aaeb880.js"><link rel="prefetch" href="/assets/js/284.cce2c80c.js"><link rel="prefetch" href="/assets/js/285.649e1ab2.js"><link rel="prefetch" href="/assets/js/286.93d1a5fb.js"><link rel="prefetch" href="/assets/js/287.95ecc60d.js"><link rel="prefetch" href="/assets/js/288.d0316c60.js"><link rel="prefetch" href="/assets/js/289.96b0da90.js"><link rel="prefetch" href="/assets/js/29.f1800df7.js"><link rel="prefetch" href="/assets/js/290.a0ec1eb0.js"><link rel="prefetch" href="/assets/js/291.000c9293.js"><link rel="prefetch" href="/assets/js/292.aa442a45.js"><link rel="prefetch" href="/assets/js/293.ad41a62d.js"><link rel="prefetch" href="/assets/js/294.d01fa093.js"><link rel="prefetch" href="/assets/js/295.988cbaa2.js"><link rel="prefetch" href="/assets/js/296.b4376d7c.js"><link rel="prefetch" href="/assets/js/297.53d3839b.js"><link rel="prefetch" href="/assets/js/298.e41d3af5.js"><link rel="prefetch" href="/assets/js/299.7530e3f7.js"><link rel="prefetch" href="/assets/js/3.0318d431.js"><link rel="prefetch" href="/assets/js/30.e022632d.js"><link rel="prefetch" href="/assets/js/300.b89cf9f0.js"><link rel="prefetch" href="/assets/js/301.538c5d13.js"><link rel="prefetch" href="/assets/js/302.e61e98d4.js"><link rel="prefetch" href="/assets/js/303.e69fdf1f.js"><link rel="prefetch" href="/assets/js/304.12cf05d2.js"><link rel="prefetch" href="/assets/js/305.05630898.js"><link rel="prefetch" href="/assets/js/306.4423e4cb.js"><link rel="prefetch" href="/assets/js/307.ec499705.js"><link rel="prefetch" href="/assets/js/308.eae04a19.js"><link rel="prefetch" href="/assets/js/309.e8cdb29d.js"><link rel="prefetch" href="/assets/js/31.a2dfbc5f.js"><link rel="prefetch" href="/assets/js/310.3770a9fc.js"><link rel="prefetch" href="/assets/js/311.79ae7adb.js"><link rel="prefetch" href="/assets/js/312.fd3baefc.js"><link rel="prefetch" href="/assets/js/313.895f6dcd.js"><link rel="prefetch" href="/assets/js/314.85943d2f.js"><link rel="prefetch" href="/assets/js/315.69631810.js"><link rel="prefetch" href="/assets/js/316.b025621c.js"><link rel="prefetch" href="/assets/js/317.7b7974aa.js"><link rel="prefetch" href="/assets/js/318.972a129d.js"><link rel="prefetch" href="/assets/js/319.65a4d2cf.js"><link rel="prefetch" href="/assets/js/32.b143e718.js"><link rel="prefetch" href="/assets/js/320.e5635579.js"><link rel="prefetch" href="/assets/js/321.845573fa.js"><link rel="prefetch" href="/assets/js/322.0f95ad9a.js"><link rel="prefetch" href="/assets/js/323.f7d22184.js"><link rel="prefetch" href="/assets/js/324.eb027f24.js"><link rel="prefetch" href="/assets/js/325.f54af6ec.js"><link rel="prefetch" href="/assets/js/326.7a921d9f.js"><link rel="prefetch" href="/assets/js/327.e9c43c17.js"><link rel="prefetch" href="/assets/js/328.586efc33.js"><link rel="prefetch" href="/assets/js/329.47017c3f.js"><link rel="prefetch" href="/assets/js/33.e17e09ac.js"><link rel="prefetch" href="/assets/js/330.81032fbd.js"><link rel="prefetch" href="/assets/js/331.ce9966db.js"><link rel="prefetch" href="/assets/js/332.c28e794e.js"><link rel="prefetch" href="/assets/js/333.4564d08a.js"><link rel="prefetch" href="/assets/js/334.3b421837.js"><link rel="prefetch" href="/assets/js/335.b2b74b9d.js"><link rel="prefetch" href="/assets/js/336.9dd1e510.js"><link rel="prefetch" href="/assets/js/337.03042431.js"><link rel="prefetch" href="/assets/js/338.1bc0b80f.js"><link rel="prefetch" href="/assets/js/339.e517fc5c.js"><link rel="prefetch" href="/assets/js/34.f287ac3d.js"><link rel="prefetch" href="/assets/js/340.f90d2df3.js"><link rel="prefetch" href="/assets/js/341.eccb4ec1.js"><link rel="prefetch" href="/assets/js/342.b3386439.js"><link rel="prefetch" href="/assets/js/343.2ee6901d.js"><link rel="prefetch" href="/assets/js/344.e6913fc7.js"><link rel="prefetch" href="/assets/js/345.a72760e7.js"><link rel="prefetch" href="/assets/js/346.13984d25.js"><link rel="prefetch" href="/assets/js/347.6b59cbaf.js"><link rel="prefetch" href="/assets/js/348.f43d5e47.js"><link rel="prefetch" href="/assets/js/349.fe8641cf.js"><link rel="prefetch" href="/assets/js/35.5a1dace7.js"><link rel="prefetch" href="/assets/js/350.0ceb9652.js"><link rel="prefetch" href="/assets/js/351.08e70696.js"><link rel="prefetch" href="/assets/js/352.958f535b.js"><link rel="prefetch" href="/assets/js/353.51463d78.js"><link rel="prefetch" href="/assets/js/354.6169e165.js"><link rel="prefetch" href="/assets/js/355.10447463.js"><link rel="prefetch" href="/assets/js/356.32983151.js"><link rel="prefetch" href="/assets/js/357.39e998b6.js"><link rel="prefetch" href="/assets/js/358.1f40aee7.js"><link rel="prefetch" href="/assets/js/359.d1e82e86.js"><link rel="prefetch" href="/assets/js/36.b6f4332a.js"><link rel="prefetch" href="/assets/js/360.9096bf48.js"><link rel="prefetch" href="/assets/js/361.e2c0815a.js"><link rel="prefetch" href="/assets/js/362.66983024.js"><link rel="prefetch" href="/assets/js/363.d7f0691d.js"><link rel="prefetch" href="/assets/js/364.d96ddc65.js"><link rel="prefetch" href="/assets/js/365.c92ad624.js"><link rel="prefetch" href="/assets/js/366.dfd66280.js"><link rel="prefetch" href="/assets/js/367.01503521.js"><link rel="prefetch" href="/assets/js/368.8d83b9c1.js"><link rel="prefetch" href="/assets/js/369.f8e08a4f.js"><link rel="prefetch" href="/assets/js/37.f1a16008.js"><link rel="prefetch" href="/assets/js/370.70b912f3.js"><link rel="prefetch" href="/assets/js/371.dcefb388.js"><link rel="prefetch" href="/assets/js/372.a81a499a.js"><link rel="prefetch" href="/assets/js/373.94458b0f.js"><link rel="prefetch" href="/assets/js/374.a406f06f.js"><link rel="prefetch" href="/assets/js/375.87287c02.js"><link rel="prefetch" href="/assets/js/376.26088425.js"><link rel="prefetch" href="/assets/js/377.b9ee096c.js"><link rel="prefetch" href="/assets/js/378.7a1b6fa7.js"><link rel="prefetch" href="/assets/js/379.3e2b62fc.js"><link rel="prefetch" href="/assets/js/38.59f5160c.js"><link rel="prefetch" href="/assets/js/380.d741385f.js"><link rel="prefetch" href="/assets/js/381.afc0104a.js"><link rel="prefetch" href="/assets/js/382.a8c02915.js"><link rel="prefetch" href="/assets/js/383.7fca9756.js"><link rel="prefetch" href="/assets/js/384.d08aa931.js"><link rel="prefetch" href="/assets/js/385.c3ab471f.js"><link rel="prefetch" href="/assets/js/386.7314b80e.js"><link rel="prefetch" href="/assets/js/387.8db3a14a.js"><link rel="prefetch" href="/assets/js/388.f618a3b3.js"><link rel="prefetch" href="/assets/js/389.4d35947d.js"><link rel="prefetch" href="/assets/js/39.3cf9af40.js"><link rel="prefetch" href="/assets/js/390.a8e04e41.js"><link rel="prefetch" href="/assets/js/391.a31e9a62.js"><link rel="prefetch" href="/assets/js/392.d9321e46.js"><link rel="prefetch" href="/assets/js/393.6c4834d0.js"><link rel="prefetch" href="/assets/js/394.fd0a0ea4.js"><link rel="prefetch" href="/assets/js/395.0f27ab48.js"><link rel="prefetch" href="/assets/js/396.70044e25.js"><link rel="prefetch" href="/assets/js/397.07b2c0a6.js"><link rel="prefetch" href="/assets/js/398.ba95a9c5.js"><link rel="prefetch" href="/assets/js/399.8b310fbc.js"><link rel="prefetch" href="/assets/js/4.45f61616.js"><link rel="prefetch" href="/assets/js/40.fcf089d7.js"><link rel="prefetch" href="/assets/js/400.7ff77c6c.js"><link rel="prefetch" href="/assets/js/401.840e0c7c.js"><link rel="prefetch" href="/assets/js/402.a722c16f.js"><link rel="prefetch" href="/assets/js/403.1a3c12fb.js"><link rel="prefetch" href="/assets/js/404.7da4d4a4.js"><link rel="prefetch" href="/assets/js/405.76a07310.js"><link rel="prefetch" href="/assets/js/406.176db1fd.js"><link rel="prefetch" href="/assets/js/407.ff3da33f.js"><link rel="prefetch" href="/assets/js/408.3b4dfb3a.js"><link rel="prefetch" href="/assets/js/409.05692a2e.js"><link rel="prefetch" href="/assets/js/41.3f0a746d.js"><link rel="prefetch" href="/assets/js/410.615dc40b.js"><link rel="prefetch" href="/assets/js/411.e542a59f.js"><link rel="prefetch" href="/assets/js/412.16fc0c97.js"><link rel="prefetch" href="/assets/js/413.b9f30c37.js"><link rel="prefetch" href="/assets/js/414.9629300e.js"><link rel="prefetch" href="/assets/js/415.5c12951e.js"><link rel="prefetch" href="/assets/js/416.3ede10bc.js"><link rel="prefetch" href="/assets/js/417.5bc08adb.js"><link rel="prefetch" href="/assets/js/418.0a54fe32.js"><link rel="prefetch" href="/assets/js/419.97ebd724.js"><link rel="prefetch" href="/assets/js/42.d0fdcdd4.js"><link rel="prefetch" href="/assets/js/420.d3f60a7a.js"><link rel="prefetch" href="/assets/js/421.6b187cc9.js"><link rel="prefetch" href="/assets/js/422.268b38aa.js"><link rel="prefetch" href="/assets/js/423.00f151fe.js"><link rel="prefetch" href="/assets/js/424.5d54e48d.js"><link rel="prefetch" href="/assets/js/425.b0e71df6.js"><link rel="prefetch" href="/assets/js/426.fb5d6c08.js"><link rel="prefetch" href="/assets/js/427.a7a42bdb.js"><link rel="prefetch" href="/assets/js/428.b41b80fb.js"><link rel="prefetch" href="/assets/js/429.aff3b223.js"><link rel="prefetch" href="/assets/js/43.7812871c.js"><link rel="prefetch" href="/assets/js/430.9bded6a2.js"><link rel="prefetch" href="/assets/js/431.fbd064dd.js"><link rel="prefetch" href="/assets/js/432.a0ccaf13.js"><link rel="prefetch" href="/assets/js/433.70729631.js"><link rel="prefetch" href="/assets/js/434.7ff21dc4.js"><link rel="prefetch" href="/assets/js/435.ba6f0c33.js"><link rel="prefetch" href="/assets/js/436.abcca44e.js"><link rel="prefetch" href="/assets/js/437.2b2333cb.js"><link rel="prefetch" href="/assets/js/438.93ea3d14.js"><link rel="prefetch" href="/assets/js/439.c1b946ea.js"><link rel="prefetch" href="/assets/js/44.d2bbbf62.js"><link rel="prefetch" href="/assets/js/440.a5c5071e.js"><link rel="prefetch" href="/assets/js/441.bad7a6f2.js"><link rel="prefetch" href="/assets/js/442.97a45e71.js"><link rel="prefetch" href="/assets/js/443.9dd7a744.js"><link rel="prefetch" href="/assets/js/444.b2e74ec9.js"><link rel="prefetch" href="/assets/js/445.181b11ad.js"><link rel="prefetch" href="/assets/js/446.1d43ea57.js"><link rel="prefetch" href="/assets/js/447.a75ca861.js"><link rel="prefetch" href="/assets/js/448.7e177e61.js"><link rel="prefetch" href="/assets/js/449.0e124a1f.js"><link rel="prefetch" href="/assets/js/45.2181b5c6.js"><link rel="prefetch" href="/assets/js/450.d18c5137.js"><link rel="prefetch" href="/assets/js/451.0296f837.js"><link rel="prefetch" href="/assets/js/452.1f5d56a5.js"><link rel="prefetch" href="/assets/js/453.6f67fa9b.js"><link rel="prefetch" href="/assets/js/454.d96cd4e8.js"><link rel="prefetch" href="/assets/js/455.488f2e23.js"><link rel="prefetch" href="/assets/js/456.264d0da2.js"><link rel="prefetch" href="/assets/js/457.329d4d26.js"><link rel="prefetch" href="/assets/js/458.d20d34f9.js"><link rel="prefetch" href="/assets/js/459.dd4fad09.js"><link rel="prefetch" href="/assets/js/46.d69710e9.js"><link rel="prefetch" href="/assets/js/460.e1f8580c.js"><link rel="prefetch" href="/assets/js/461.d47e1ab7.js"><link rel="prefetch" href="/assets/js/462.54b49f34.js"><link rel="prefetch" href="/assets/js/463.2d1bb289.js"><link rel="prefetch" href="/assets/js/464.28d2b2fe.js"><link rel="prefetch" href="/assets/js/465.474d09dd.js"><link rel="prefetch" href="/assets/js/466.3d79bf1d.js"><link rel="prefetch" href="/assets/js/467.0e38992e.js"><link rel="prefetch" href="/assets/js/468.23f8dbdb.js"><link rel="prefetch" href="/assets/js/469.424ab64e.js"><link rel="prefetch" href="/assets/js/47.fa77c18f.js"><link rel="prefetch" href="/assets/js/470.8e15adc4.js"><link rel="prefetch" href="/assets/js/471.e478b277.js"><link rel="prefetch" href="/assets/js/472.75eed247.js"><link rel="prefetch" href="/assets/js/473.676ac02f.js"><link rel="prefetch" href="/assets/js/474.ec676f10.js"><link rel="prefetch" href="/assets/js/475.0b3a7bb3.js"><link rel="prefetch" href="/assets/js/476.1dccc2bf.js"><link rel="prefetch" href="/assets/js/477.19774d6a.js"><link rel="prefetch" href="/assets/js/478.562bcdfb.js"><link rel="prefetch" href="/assets/js/479.0fdf39e1.js"><link rel="prefetch" href="/assets/js/48.55ba7067.js"><link rel="prefetch" href="/assets/js/480.32cb0959.js"><link rel="prefetch" href="/assets/js/481.39744803.js"><link rel="prefetch" href="/assets/js/482.82ff750c.js"><link rel="prefetch" href="/assets/js/483.59be5f3b.js"><link rel="prefetch" href="/assets/js/484.b47730ba.js"><link rel="prefetch" href="/assets/js/485.514e284f.js"><link rel="prefetch" href="/assets/js/486.8d407228.js"><link rel="prefetch" href="/assets/js/487.623afb9a.js"><link rel="prefetch" href="/assets/js/488.d575377d.js"><link rel="prefetch" href="/assets/js/49.369b2ef4.js"><link rel="prefetch" href="/assets/js/5.89e027e6.js"><link rel="prefetch" href="/assets/js/50.32e51808.js"><link rel="prefetch" href="/assets/js/51.48af1f55.js"><link rel="prefetch" href="/assets/js/52.0ff3366f.js"><link rel="prefetch" href="/assets/js/53.f663d530.js"><link rel="prefetch" href="/assets/js/54.57eabb55.js"><link rel="prefetch" href="/assets/js/55.00e0bdd0.js"><link rel="prefetch" href="/assets/js/56.b638bc9a.js"><link rel="prefetch" href="/assets/js/57.68420705.js"><link rel="prefetch" href="/assets/js/58.f0a325a2.js"><link rel="prefetch" href="/assets/js/59.30debc93.js"><link rel="prefetch" href="/assets/js/6.0db48d19.js"><link rel="prefetch" href="/assets/js/60.48490f44.js"><link rel="prefetch" href="/assets/js/61.26a984a9.js"><link rel="prefetch" href="/assets/js/62.f0add27d.js"><link rel="prefetch" href="/assets/js/63.07c42d31.js"><link rel="prefetch" href="/assets/js/65.c159a057.js"><link rel="prefetch" href="/assets/js/66.80e96020.js"><link rel="prefetch" href="/assets/js/67.42eabf7d.js"><link rel="prefetch" href="/assets/js/68.2a7e9954.js"><link rel="prefetch" href="/assets/js/69.4579e421.js"><link rel="prefetch" href="/assets/js/7.037ecfb1.js"><link rel="prefetch" href="/assets/js/70.4e7b95d4.js"><link rel="prefetch" href="/assets/js/71.5df75825.js"><link rel="prefetch" href="/assets/js/72.6239ec2a.js"><link rel="prefetch" href="/assets/js/73.c2458335.js"><link rel="prefetch" href="/assets/js/74.b86599e1.js"><link rel="prefetch" href="/assets/js/75.8d14cab7.js"><link rel="prefetch" href="/assets/js/76.82bf4b00.js"><link rel="prefetch" href="/assets/js/77.f5a890cc.js"><link rel="prefetch" href="/assets/js/78.f3c574f3.js"><link rel="prefetch" href="/assets/js/79.c9c56bf3.js"><link rel="prefetch" href="/assets/js/8.03d32196.js"><link rel="prefetch" href="/assets/js/80.24c4483b.js"><link rel="prefetch" href="/assets/js/81.e6653250.js"><link rel="prefetch" href="/assets/js/82.0da4ae5d.js"><link rel="prefetch" href="/assets/js/83.89a8c965.js"><link rel="prefetch" href="/assets/js/84.56206c88.js"><link rel="prefetch" href="/assets/js/85.0daf7cf7.js"><link rel="prefetch" href="/assets/js/86.0a17b684.js"><link rel="prefetch" href="/assets/js/87.f7cf9412.js"><link rel="prefetch" href="/assets/js/88.22341e3f.js"><link rel="prefetch" href="/assets/js/89.2166c8bb.js"><link rel="prefetch" href="/assets/js/9.a241a058.js"><link rel="prefetch" href="/assets/js/90.9440815d.js"><link rel="prefetch" href="/assets/js/91.5ea69e27.js"><link rel="prefetch" href="/assets/js/92.cea1c8dd.js"><link rel="prefetch" href="/assets/js/93.2e94ab93.js"><link rel="prefetch" href="/assets/js/94.1674ba0c.js"><link rel="prefetch" href="/assets/js/95.c6ba057e.js"><link rel="prefetch" href="/assets/js/96.ee719565.js"><link rel="prefetch" href="/assets/js/97.a814f163.js"><link rel="prefetch" href="/assets/js/98.748b1098.js"><link rel="prefetch" href="/assets/js/99.c6176c0d.js">
    <link rel="stylesheet" href="/assets/css/0.styles.e57fdc06.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/" class="home-link router-link-active"><img src="/logo.png" alt="房飞跃的博客" class="logo"> <span class="site-name can-hide">房飞跃的博客</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="前端" class="dropdown-title"><span class="title">前端</span> <span class="arrow down"></span></button> <button type="button" aria-label="前端" class="mobile-dropdown-title"><span class="title">前端</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>
          Vue
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/books/深入浅出Vue.js/01.html" class="nav-link">
  深入浅出Vue
</a></li><li class="dropdown-subitem"><a href="/front/vue/vue/01.html" class="nav-link">
  Vue
</a></li><li class="dropdown-subitem"><a href="/front/vue/vue-router/01.html" class="nav-link">
  VueRouter
</a></li><li class="dropdown-subitem"><a href="/front/vue/Vuex/01.html" class="nav-link">
  Vuex
</a></li><li class="dropdown-subitem"><a href="/front/vue/vue3/01.html" class="nav-link">
  Vue3核心剖析
</a></li><li class="dropdown-subitem"><a href="/front/vue/Vue知识点简单梳理/01.html" class="nav-link">
  Vue知识点简单梳理
</a></li></ul></li><li class="dropdown-item"><h4>
          React
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/books/深入React技术栈/01.html" class="nav-link">
  深入React技术栈
</a></li><li class="dropdown-subitem"><a href="/front/react/React进阶实践指南/01.html" class="nav-link">
  React进阶实践指南
</a></li><li class="dropdown-subitem"><a href="/front/react/React知识点简单梳理/01.html" class="nav-link">
  React知识点简单梳理
</a></li></ul></li><li class="dropdown-item"><h4>
          混合开发
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/front/混合开发/01.html" class="nav-link">
  混合开发探究
</a></li></ul></li><li class="dropdown-item"><h4>
          TypeScript
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/front/ts/极简入门Typescript/01.html" class="nav-link">
  极简入门Typescript
</a></li></ul></li><li class="dropdown-item"><h4>
          Webpack
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/front/webpack/极简入门webpack/01.html" class="nav-link">
  极简入门
</a></li><li class="dropdown-subitem"><a href="/front/webpack/常见面试题/01.html" class="nav-link">
  常见面试题
</a></li></ul></li><li class="dropdown-item"><h4>
          设计模式
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/front/设计模式/JS设计模式核心原理和应用实践/01.html" class="nav-link">
  JS设计模式核心原理和应用实践
</a></li></ul></li><li class="dropdown-item"><h4>
          算法和数据结构
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/front/算法和数据结构/入门级算法/01.html" class="nav-link">
  入门级算法
</a></li><li class="dropdown-subitem"><a href="/front/算法和数据结构/常见算法/01.html" class="nav-link">
  常见算法
</a></li><li class="dropdown-subitem"><a href="/front/算法和数据结构/常见数据结构/01.html" class="nav-link">
  常见数据结构
</a></li><li class="dropdown-subitem"><a href="/front/算法和数据结构/前端算法与数据结构/01.html" class="nav-link">
  前端算法与数据结构
</a></li></ul></li><li class="dropdown-item"><h4>
          基础必备
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/front/base/html必备/01.html" class="nav-link">
  HTML必备
</a></li><li class="dropdown-subitem"><a href="/front/base/CSS必备/01.html" class="nav-link">
  CSS必备
</a></li><li class="dropdown-subitem"><a href="/front/base/JS基础/01.html" class="nav-link">
  JS基础
</a></li><li class="dropdown-subitem"><a href="/front/base/JS进阶/01.html" class="nav-link">
  JS进阶
</a></li><li class="dropdown-subitem"><a href="/front/base/JS练习/01.html" class="nav-link">
  JS练习
</a></li><li class="dropdown-subitem"><a href="/front/base/网络基础/01.html" class="nav-link">
  网络基础
</a></li><li class="dropdown-subitem"><a href="/books/JS高级程序设计/01.html" class="nav-link">
  JS高级程序设计
</a></li><li class="dropdown-subitem"><a href="/front/base/浏览器相关基础/01.html" class="nav-link">
  浏览器相关基础
</a></li></ul></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="电子" class="dropdown-title"><span class="title">电子</span> <span class="arrow down"></span></button> <button type="button" aria-label="电子" class="mobile-dropdown-title"><span class="title">电子</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>
          STM32
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/电子/STM32四轴飞行器/01.html" class="nav-link">
  STM32四轴飞行器
</a></li></ul></li><li class="dropdown-item"><h4>
          Arduino
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/电子/Arduino墙画机/01.html" class="nav-link">
  Arduino墙画机
</a></li><li class="dropdown-subitem"><a href="/电子/Arduino四轴飞行器/01.html" class="nav-link">
  Arduino四轴飞行器
</a></li><li class="dropdown-subitem"><a href="/电子/Arduino四足仿生机器人/01.html" class="nav-link">
  Arduino四足仿生机器人
</a></li></ul></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="关于" class="dropdown-title"><span class="title">关于</span> <span class="arrow down"></span></button> <button type="button" aria-label="关于" class="mobile-dropdown-title"><span class="title">关于</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/关于我/01.html" class="nav-link">
  关于我
</a></li><li class="dropdown-item"><!----> <a href="https://github.com/fangfeiyue" target="_blank" rel="noopener noreferrer" class="nav-link external">
  Github
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div> <!----></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="前端" class="dropdown-title"><span class="title">前端</span> <span class="arrow down"></span></button> <button type="button" aria-label="前端" class="mobile-dropdown-title"><span class="title">前端</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>
          Vue
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/books/深入浅出Vue.js/01.html" class="nav-link">
  深入浅出Vue
</a></li><li class="dropdown-subitem"><a href="/front/vue/vue/01.html" class="nav-link">
  Vue
</a></li><li class="dropdown-subitem"><a href="/front/vue/vue-router/01.html" class="nav-link">
  VueRouter
</a></li><li class="dropdown-subitem"><a href="/front/vue/Vuex/01.html" class="nav-link">
  Vuex
</a></li><li class="dropdown-subitem"><a href="/front/vue/vue3/01.html" class="nav-link">
  Vue3核心剖析
</a></li><li class="dropdown-subitem"><a href="/front/vue/Vue知识点简单梳理/01.html" class="nav-link">
  Vue知识点简单梳理
</a></li></ul></li><li class="dropdown-item"><h4>
          React
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/books/深入React技术栈/01.html" class="nav-link">
  深入React技术栈
</a></li><li class="dropdown-subitem"><a href="/front/react/React进阶实践指南/01.html" class="nav-link">
  React进阶实践指南
</a></li><li class="dropdown-subitem"><a href="/front/react/React知识点简单梳理/01.html" class="nav-link">
  React知识点简单梳理
</a></li></ul></li><li class="dropdown-item"><h4>
          混合开发
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/front/混合开发/01.html" class="nav-link">
  混合开发探究
</a></li></ul></li><li class="dropdown-item"><h4>
          TypeScript
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/front/ts/极简入门Typescript/01.html" class="nav-link">
  极简入门Typescript
</a></li></ul></li><li class="dropdown-item"><h4>
          Webpack
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/front/webpack/极简入门webpack/01.html" class="nav-link">
  极简入门
</a></li><li class="dropdown-subitem"><a href="/front/webpack/常见面试题/01.html" class="nav-link">
  常见面试题
</a></li></ul></li><li class="dropdown-item"><h4>
          设计模式
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/front/设计模式/JS设计模式核心原理和应用实践/01.html" class="nav-link">
  JS设计模式核心原理和应用实践
</a></li></ul></li><li class="dropdown-item"><h4>
          算法和数据结构
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/front/算法和数据结构/入门级算法/01.html" class="nav-link">
  入门级算法
</a></li><li class="dropdown-subitem"><a href="/front/算法和数据结构/常见算法/01.html" class="nav-link">
  常见算法
</a></li><li class="dropdown-subitem"><a href="/front/算法和数据结构/常见数据结构/01.html" class="nav-link">
  常见数据结构
</a></li><li class="dropdown-subitem"><a href="/front/算法和数据结构/前端算法与数据结构/01.html" class="nav-link">
  前端算法与数据结构
</a></li></ul></li><li class="dropdown-item"><h4>
          基础必备
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/front/base/html必备/01.html" class="nav-link">
  HTML必备
</a></li><li class="dropdown-subitem"><a href="/front/base/CSS必备/01.html" class="nav-link">
  CSS必备
</a></li><li class="dropdown-subitem"><a href="/front/base/JS基础/01.html" class="nav-link">
  JS基础
</a></li><li class="dropdown-subitem"><a href="/front/base/JS进阶/01.html" class="nav-link">
  JS进阶
</a></li><li class="dropdown-subitem"><a href="/front/base/JS练习/01.html" class="nav-link">
  JS练习
</a></li><li class="dropdown-subitem"><a href="/front/base/网络基础/01.html" class="nav-link">
  网络基础
</a></li><li class="dropdown-subitem"><a href="/books/JS高级程序设计/01.html" class="nav-link">
  JS高级程序设计
</a></li><li class="dropdown-subitem"><a href="/front/base/浏览器相关基础/01.html" class="nav-link">
  浏览器相关基础
</a></li></ul></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="电子" class="dropdown-title"><span class="title">电子</span> <span class="arrow down"></span></button> <button type="button" aria-label="电子" class="mobile-dropdown-title"><span class="title">电子</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>
          STM32
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/电子/STM32四轴飞行器/01.html" class="nav-link">
  STM32四轴飞行器
</a></li></ul></li><li class="dropdown-item"><h4>
          Arduino
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/电子/Arduino墙画机/01.html" class="nav-link">
  Arduino墙画机
</a></li><li class="dropdown-subitem"><a href="/电子/Arduino四轴飞行器/01.html" class="nav-link">
  Arduino四轴飞行器
</a></li><li class="dropdown-subitem"><a href="/电子/Arduino四足仿生机器人/01.html" class="nav-link">
  Arduino四足仿生机器人
</a></li></ul></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="关于" class="dropdown-title"><span class="title">关于</span> <span class="arrow down"></span></button> <button type="button" aria-label="关于" class="mobile-dropdown-title"><span class="title">关于</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/关于我/01.html" class="nav-link">
  关于我
</a></li><li class="dropdown-item"><!----> <a href="https://github.com/fangfeiyue" target="_blank" rel="noopener noreferrer" class="nav-link external">
  Github
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div> <!----></nav>  <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>WEB电子书阅读器</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/project/web电子书阅读器/01.html" class="active sidebar-link">ebook</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#阅读器工作原理" class="sidebar-link">阅读器工作原理</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#epub标准介绍" class="sidebar-link">ePub标准介绍</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#epubjs阅读器引擎介绍" class="sidebar-link">epubjs阅读器引擎介绍</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#nvm" class="sidebar-link">nvm</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#vue-cli3-0环境搭建" class="sidebar-link">Vue CLI3.0环境搭建</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#准备web字体" class="sidebar-link">准备web字体</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#viewport设置和rem设置" class="sidebar-link">viewport设置和rem设置</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#global-scss和reset-scss设置" class="sidebar-link">global.scss和reset.scss设置</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#vuex-vue-devtool" class="sidebar-link">vuex+vue-devtool</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#搭建静态资源服务器" class="sidebar-link">搭建静态资源服务器</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#阅读器需求分析" class="sidebar-link">阅读器需求分析</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#阅读器的解析和渲染" class="sidebar-link">阅读器的解析和渲染</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#阅读器翻页功能实现" class="sidebar-link">阅读器翻页功能实现</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#标题栏和菜单栏实现" class="sidebar-link">标题栏和菜单栏实现</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#字号设置ui实现" class="sidebar-link">字号设置UI实现</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#字号设置功能实现" class="sidebar-link">字号设置功能实现</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#字体设置弹窗ui实现" class="sidebar-link">字体设置弹窗UI实现</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#字体设置弹窗功能实现" class="sidebar-link">字体设置弹窗功能实现</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#字号和字体设置离线存储" class="sidebar-link">字号和字体设置离线存储</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#字体设置标题国际化" class="sidebar-link">字体设置标题国际化</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#阅读器主题功能实现" class="sidebar-link">阅读器主题功能实现</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#全局主题设置功能实现" class="sidebar-link">全局主题设置功能实现</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#阅读进度功能实现-进度面板-分页逻辑" class="sidebar-link">阅读进度功能实现（进度面板+分页逻辑）</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#阅读进度功能实现-进度拖动功能" class="sidebar-link">阅读进度功能实现（进度拖动功能）</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#阅读进度功能实现-上下章节切换功能" class="sidebar-link">阅读进度功能实现（上下章节切换功能）</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#阅读进度功能实现-章节切换和进度同步" class="sidebar-link">阅读进度功能实现（章节切换和进度同步）</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#阅读进度功能实现-保存阅读进度功能" class="sidebar-link">阅读进度功能实现（保存阅读进度功能）</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#目录功能实现-目录浮出效果" class="sidebar-link">目录功能实现（目录浮出效果）</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#目录功能实现-tab选项切换和搜索效果" class="sidebar-link">目录功能实现（Tab选项切换和搜索效果）</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#目录功能实现-图书内容布局" class="sidebar-link">目录功能实现（图书内容布局）</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#目录功能实现-图书内容样式" class="sidebar-link">目录功能实现（图书内容样式）</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#目录功能实现-目录数据结构开发" class="sidebar-link">目录功能实现（目录数据结构开发）</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#目录功能实现-多级目录功能" class="sidebar-link">目录功能实现（多级目录功能）</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#全文搜索功能实现-搜索算法-数组降维" class="sidebar-link">全文搜索功能实现（搜索算法+数组降维）</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#全文搜索功能实现-搜索关键字高亮-搜索结果高亮显示" class="sidebar-link">全文搜索功能实现 （搜索关键字高亮+搜索结果高亮显示）</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#书签手势实现-页面下拉" class="sidebar-link">书签手势实现（页面下拉）</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#书签手势实现-书签组件" class="sidebar-link">书签手势实现（书签组件）</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#书签手势实现-下拉状态管理" class="sidebar-link">书签手势实现（下拉状态管理）</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#书签手势实现-书签添加删除交互" class="sidebar-link">书签手势实现（书签添加删除交互）</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#epubcfi原理介绍" class="sidebar-link">EpubCFI原理介绍</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#书签功能实现" class="sidebar-link">书签功能实现</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#阅读模式介绍" class="sidebar-link">阅读模式介绍</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#微信兼容性调整" class="sidebar-link">微信兼容性调整</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#书签支持鼠标事件" class="sidebar-link">书签支持鼠标事件</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#阅读器分页算法实现" class="sidebar-link">阅读器分页算法实现</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#书城首页开发-框架页面-路由配置" class="sidebar-link">书城首页开发（框架页面+路由配置）</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#书城首页-标题-搜索框布局" class="sidebar-link">书城首页（标题+搜索框布局）</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#书城首页-标题-搜索框交互设计分析" class="sidebar-link">书城首页（标题+搜索框交互设计分析）</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#书城首页-标题交互动画实现" class="sidebar-link">书城首页（标题交互动画实现）</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#书城首页-搜索框交互动画实现" class="sidebar-link">书城首页（搜索框交互动画实现</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#书城首页-热门搜索布局" class="sidebar-link">书城首页（热门搜索布局）</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#书城首页-热门搜索交互" class="sidebar-link">书城首页（热门搜索交互）</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#书城首页-推荐页面布局" class="sidebar-link">书城首页（推荐页面布局）</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#书城首页-卡片翻转动画实现" class="sidebar-link">书城首页（卡片翻转动画实现）</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#书城首页-卡片翻转动画重置" class="sidebar-link">书城首页（卡片翻转动画重置）</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#书城首页-卡片登场keyframes动画讲解" class="sidebar-link">书城首页（卡片登场keyframes动画讲解）</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#书城首页-烟花动画实现" class="sidebar-link">书城首页（烟花动画实现）</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#书城首页-mockjs使用方法讲解" class="sidebar-link">书城首页（mockjs使用方法讲解）</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#书城首页-推荐图书布局-动画" class="sidebar-link">书城首页（推荐图书布局+动画）</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#书城首页-首页图书布局实现" class="sidebar-link">书城首页（首页图书布局实现）</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#书城详情页开发" class="sidebar-link">书城详情页开发</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#书城列表页开发" class="sidebar-link">书城列表页开发</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#第七章总结" class="sidebar-link">第七章总结</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#书架" class="sidebar-link">书架</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#书架标题组件布局实现" class="sidebar-link">书架标题组件布局实现</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#书架标题组件交互实现" class="sidebar-link">书架标题组件交互实现</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#书架搜索框布局实现" class="sidebar-link">书架搜索框布局实现</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#书架搜索框交互实现" class="sidebar-link">书架搜索框交互实现</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#书架数据结构设计-数据获取" class="sidebar-link">书架数据结构设计+数据获取</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#书架标题-搜索框样式优化" class="sidebar-link">书架标题+搜索框样式优化</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#书架图书列表实现" class="sidebar-link">书架图书列表实现</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#书架图书列表布局" class="sidebar-link">书架图书列表布局</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#书架图书组件开发-单书封面-分类书籍封面实现" class="sidebar-link">书架图书组件开发(单书封面+分类书籍封面实现)</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#书架图书组件开发-添加-编辑实现" class="sidebar-link">书架图书组件开发(添加+编辑实现)</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#书架编辑模式开发" class="sidebar-link">书架编辑模式开发</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#书架弹出框组件开发" class="sidebar-link">书架弹出框组件开发</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#书架弹出框功能开发" class="sidebar-link">书架弹出框功能开发</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#书架弹出框功能开发-2" class="sidebar-link">书架弹出框功能开发</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#电子书离线缓存功能开发" class="sidebar-link">电子书离线缓存功能开发</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#电子书缓存删除功能开发" class="sidebar-link">电子书缓存删除功能开发</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#书架缓存-离线阅读功能开发" class="sidebar-link">书架缓存+离线阅读功能开发</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#书架分组功能开发" class="sidebar-link">书架分组功能开发</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#书架列表过渡动画开发" class="sidebar-link">书架列表过渡动画开发</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#书架分类列表开发" class="sidebar-link">书架分类列表开发</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#书架分组功能优化" class="sidebar-link">书架分组功能优化</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#书架修改分组功能开发" class="sidebar-link">书架修改分组功能开发</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#vue项目构建" class="sidebar-link">Vue项目构建</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#功能优化-构建问题处理" class="sidebar-link">功能优化+构建问题处理</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#数据库环境准备" class="sidebar-link">数据库环境准备</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#node-js-express编写api" class="sidebar-link">Node.js+express编写API</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#书城首页api开发" class="sidebar-link">书城首页API开发</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#书城首页api开发-2" class="sidebar-link">书城首页API开发</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#书城首页前后端api联调-解决cors跨域" class="sidebar-link">书城首页前后端API联调（解决CORS跨域）</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#电子书详情api开发" class="sidebar-link">电子书详情API开发</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#电子书列表api开发" class="sidebar-link">电子书列表API开发</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#后端api源码上传git演示" class="sidebar-link">后端API源码上传git演示</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#阿里云ecs服务器开通" class="sidebar-link">阿里云ECS服务器开通</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#centos-node-js环境搭建" class="sidebar-link">CentOS Node.js环境搭建</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#centos-ngnix环境搭建" class="sidebar-link">CentOS Ngnix环境搭建</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#centos-git部署-免密更新" class="sidebar-link">CentOS git部署+免密更新</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#centos-前端项目构建和发布" class="sidebar-link">CentOS 前端项目构建和发布</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#centos-mysql环境安装" class="sidebar-link">CentOS MySQL环境安装</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#centos-一键部署脚本开发" class="sidebar-link">CentOS 一键部署脚本开发</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#阿里云域名注册、解析与备案流程" class="sidebar-link">阿里云域名注册、解析与备案流程</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#升级centos到8-0的错误处理" class="sidebar-link">升级centos到8.0的错误处理</a></li><li class="sidebar-sub-header"><a href="/project/web电子书阅读器/01.html#路由" class="sidebar-link">路由</a></li></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="ebook"><a href="#ebook" class="header-anchor">#</a> ebook</h1> <p>运行项目</p> <h2 id="阅读器工作原理"><a href="#阅读器工作原理" class="header-anchor">#</a> 阅读器工作原理</h2> <p>将各种格式的电子书通过阅读器引擎解析为阅读器可识别的格式。然后将解析的结果渲染到界面上。 并提供一系列的辅助功能，如字体、主题设置等等</p> <p>第一步是解压</p> <p>第二步 在META-INF文件夹中找到container.xml文件，再找到rootfile所对应的文件路径。</p> <p>第三步 解析content.opf文件</p> <p>模拟阅读器引擎如何解析一个epub文件。将epub文件后缀名改为.zip，使用压缩工具进行解压。打开解压后的文件夹，</p> <p>metadata对应的是电子书的基本信息。manifest对应的是电子书所有的资源文件及路径。spine对应的是电子书的排列顺序，对电子书资源排序哪个在前哪个在后。spine中的toc属性对应电子书的目录文件。guide对应指南信息。每本电子书的结构可能不一定完全一样，但是解析步骤是一样的。</p> <h2 id="epub标准介绍"><a href="#epub标准介绍" class="header-anchor">#</a> ePub标准介绍</h2> <p>ePub标准是IDPF制定的电子书标准，IDPF国际数字出版论坛，是一个国际组织，致力于推广电子出版物。IDPF拥有14个董事会席位，收入来源主要是会员费。</p> <p>ePub标准主要解决电子书的分发、管理和加密等问题，ePub的核心是:ZIP+XML+资源文件（HTML+CSS+图片+音频+视频等）</p> <p>ePub的核心就是利用zip技术将不同类型的文件打包成为一个 epub文件用xml技术进行配置管理，用各类资源文件如HTML、CSS、图片、音频、视频等实现电子书的展示。</p> <h2 id="epubjs阅读器引擎介绍"><a href="#epubjs阅读器引擎介绍" class="header-anchor">#</a> epubjs阅读器引擎介绍</h2> <p>epubjs是一个技术JS的开源的ePub阅读器引擎，它解决了epub电子书的解析、渲染、定位等技术难题，同时提供了媲美原生app的阅读体验。</p> <p>epubjs核心类介绍：</p> <p>Book类，完成了阅读器的解析，Rendition实现了阅读器的渲染 Locations实现了阅读器的定位。Navigation存储了目录信息。ViewManager负责渲染出来的视图的管理。EpubCFI利用了epub的CFI标准来进行文字级别的定位。</p> <h2 id="nvm"><a href="#nvm" class="header-anchor">#</a> nvm</h2> <p>nvm或者nvm-windows可以在电脑上管理多个node版本。</p> <p>安装：</p> <div class="language-js extra-class"><pre class="language-js"><code>curl <span class="token operator">-</span>o<span class="token operator">-</span> https<span class="token operator">:</span><span class="token operator">/</span><span class="token operator">/</span>raw<span class="token punctuation">.</span>githubusercontent<span class="token punctuation">.</span>com<span class="token operator">/</span>nvm<span class="token operator">-</span>sh<span class="token operator">/</span>nvm<span class="token operator">/</span>v0<span class="token punctuation">.</span><span class="token number">37.2</span><span class="token operator">/</span>install<span class="token punctuation">.</span>sh <span class="token operator">|</span> bash
</code></pre></div><p>执行完上述命令后</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">export</span> <span class="token constant">NVM_DIR</span><span class="token operator">=</span><span class="token string">&quot;$([ -z &quot;</span>$<span class="token punctuation">{</span><span class="token constant">XDG_CONFIG_HOME</span><span class="token operator">-</span><span class="token punctuation">}</span><span class="token string">&quot; ] &amp;&amp; printf %s &quot;</span>$<span class="token punctuation">{</span><span class="token constant">HOME</span><span class="token punctuation">}</span><span class="token operator">/</span><span class="token punctuation">.</span>nvm<span class="token string">&quot; || printf %s &quot;</span>$<span class="token punctuation">{</span><span class="token constant">XDG_CONFIG_HOME</span><span class="token punctuation">}</span><span class="token operator">/</span>nvm<span class="token string">&quot;)&quot;</span>
<span class="token punctuation">[</span> <span class="token operator">-</span>s <span class="token string">&quot;$NVM_DIR/nvm.sh&quot;</span> <span class="token punctuation">]</span> <span class="token operator">&amp;&amp;</span> \<span class="token punctuation">.</span> <span class="token string">&quot;$NVM_DIR/nvm.sh&quot;</span> # This loads nvm
</code></pre></div><p>可以通过<code>cat ~/.bash_profile</code>查看</p> <p>然后执行<code>source ~/.bash_profile</code>让环境变量生效。</p> <h3 id="安装node"><a href="#安装node" class="header-anchor">#</a> 安装node</h3> <div class="language- extra-class"><pre class="language-text"><code># 安装最新版本node
nvm install node
# 安装指定版本 xxx代表node版本号如10.10.0
nvm install xxx
</code></pre></div><h3 id="切换node版本"><a href="#切换node版本" class="header-anchor">#</a> 切换node版本</h3> <div class="language- extra-class"><pre class="language-text"><code># xxx代表node版本号，如10.10.0
nvm use xxx
</code></pre></div><h3 id="卸载nvm"><a href="#卸载nvm" class="header-anchor">#</a> 卸载nvm</h3> <div class="language- extra-class"><pre class="language-text"><code>$ rm -rf &quot;$NVM_DIR&quot;
</code></pre></div><p>执行完上述命令后，还要打开<code>~/.bashrc</code>文件，删除如下代码：</p> <div class="language- extra-class"><pre class="language-text"><code>export NVM_DIR=&quot;$HOME/.nvm&quot;
[ -s &quot;$NVM_DIR/nvm.sh&quot; ] &amp;&amp; \. &quot;$NVM_DIR/nvm.sh&quot; # This loads nvm
[[ -r $NVM_DIR/bash_completion ]] &amp;&amp; \. $NVM_DIR/bash_completion
</code></pre></div><h2 id="vue-cli3-0环境搭建"><a href="#vue-cli3-0环境搭建" class="header-anchor">#</a> Vue CLI3.0环境搭建</h2> <p>卸载老版本的，因为新的vue-cli包名变成了<code>@vue/cli</code>和老版本是不兼容的</p> <div class="language-js extra-class"><pre class="language-js"><code>npm uninstall vue<span class="token operator">-</span>cli <span class="token operator">-</span>g
</code></pre></div><p>安装新版本的</p> <div class="language-js extra-class"><pre class="language-js"><code>npm install <span class="token operator">-</span>g @vue<span class="token operator">/</span>cli
</code></pre></div><p>如果想做原型开发</p> <div class="language-js extra-class"><pre class="language-js"><code>npm install <span class="token operator">-</span>g @vue<span class="token operator">/</span>cli<span class="token operator">-</span>service<span class="token operator">-</span>global
</code></pre></div><p>创建项目</p> <div class="language- extra-class"><pre class="language-text"><code># xxx代表项目名称
vue create xxx
</code></pre></div><p>这里我们执行</p> <div class="language- extra-class"><pre class="language-text"><code>vue create ebook
</code></pre></div><p>安装epubjs</p> <div class="language-js extra-class"><pre class="language-js"><code>npm install epubjs <span class="token operator">--</span>save
</code></pre></div><p>简单使用</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token operator">&lt;</span>template<span class="token operator">&gt;</span>
  <span class="token operator">&lt;</span>div id<span class="token operator">=</span><span class="token string">&quot;book&quot;</span><span class="token operator">&gt;</span><span class="token operator">&lt;</span><span class="token operator">/</span>div<span class="token operator">&gt;</span>
<span class="token operator">&lt;</span><span class="token operator">/</span>template<span class="token operator">&gt;</span>
<span class="token operator">&lt;</span>script<span class="token operator">&gt;</span>
<span class="token keyword">import</span> Epub <span class="token keyword">from</span> <span class="token string">'epubjs'</span>
<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token punctuation">{</span>
  <span class="token function">mounted</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>book <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Epub</span><span class="token punctuation">(</span><span class="token string">'/2014_Book_Self-ReportedPopulationHealthA.epub'</span><span class="token punctuation">)</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>book<span class="token punctuation">.</span><span class="token function">renderTo</span><span class="token punctuation">(</span><span class="token string">'book'</span><span class="token punctuation">,</span> <span class="token punctuation">{</span>
      width<span class="token operator">:</span> window<span class="token punctuation">.</span>innerWidth<span class="token punctuation">,</span>
      height<span class="token operator">:</span> window<span class="token punctuation">.</span>innerHeight
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">display</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token operator">&lt;</span><span class="token operator">/</span>script<span class="token operator">&gt;</span>
</code></pre></div><p>安装sass</p> <div class="language- extra-class"><pre class="language-text"><code>npm i node-sass sass-loader -D
</code></pre></div><p>运行项目如果报<code>TypeError: this.getOptions is not a function</code>错误，是因为sass-loader版本过高，可以安装低版本的sass-loader</p> <div class="language- extra-class"><pre class="language-text"><code># 卸载sass-loader
npm uninstall -D sass-loader
# 安装sass-loader
npm install -D sass-loader@7.x
</code></pre></div><h2 id="准备web字体"><a href="#准备web字体" class="header-anchor">#</a> 准备web字体</h2> <p>在 CSS3 之前，web 设计师必须使用已在用户计算机上安装好的字体。</p> <p>通过 CSS3，web 设计师可以使用他们喜欢的任意字体。</p> <p>当您找到或购买到希望使用的字体时，可将该字体文件存放到 web 服务器上，它会在需要时被自动下载到用户的计算机上。</p> <p>您“自己的”的字体是在 CSS3 @font-face 规则中定义的。</p> <p>在新的 @font-face 规则中，您必须首先定义字体的名称（比如 myFirstFont），然后指向该字体文件。</p> <p>如需为 HTML 元素使用字体，请通过 font-family 属性来引用字体的名称 (myFirstFont)：</p> <div class="language-css extra-class"><pre class="language-css"><code>&lt;style&gt; 
  <span class="token atrule"><span class="token rule">@font-face</span></span>
  <span class="token punctuation">{</span>
    <span class="token property">font-family</span><span class="token punctuation">:</span> myFirstFont<span class="token punctuation">;</span>
    <span class="token property">src</span><span class="token punctuation">:</span> <span class="token url"><span class="token function">url</span><span class="token punctuation">(</span><span class="token string url">'Sansation_Light.ttf'</span><span class="token punctuation">)</span></span><span class="token punctuation">,</span>
        <span class="token url"><span class="token function">url</span><span class="token punctuation">(</span><span class="token string url">'Sansation_Light.eot'</span><span class="token punctuation">)</span></span><span class="token punctuation">;</span> <span class="token comment">/* IE9+ */</span>
  <span class="token punctuation">}</span>

  <span class="token selector">div</span>
  <span class="token punctuation">{</span>
    <span class="token property">font-family</span><span class="token punctuation">:</span>myFirstFont<span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
&lt;/style&gt;
</code></pre></div><h2 id="viewport设置和rem设置"><a href="#viewport设置和rem设置" class="header-anchor">#</a> viewport设置和rem设置</h2> <p>viewport设置</p> <div class="language-html extra-class"><pre class="language-html"><code><span class="token comment">&lt;!-- 
  user-scalable 设置是否允许用户缩放
  initial-scale 设置初始的缩放比例
  minimum-scale 设置允许用户缩放到的最小比例
  maximum-scale 设置允许用户缩放到的最大比例
--&gt;</span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>meta</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>viewport<span class="token punctuation">&quot;</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>width=device-width,initial-scale=1.0,maximum-scale=1.0,minimum=1.0,user-scalable=no<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
</code></pre></div><p>rem设置</p> <p>rem的主要作用是为了实现自适应布局</p> <div class="language-js extra-class"><pre class="language-js"><code>document<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'DOMContentLoaded'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> html <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">'html'</span><span class="token punctuation">)</span>
  <span class="token keyword">let</span> fontSize <span class="token operator">=</span> window<span class="token punctuation">.</span>innerWidth <span class="token operator">/</span> <span class="token number">10</span>
  fontSize <span class="token operator">=</span> fontSize <span class="token operator">&gt;</span> <span class="token number">50</span> <span class="token operator">?</span> <span class="token number">50</span> <span class="token operator">:</span> fontSize
  html<span class="token punctuation">.</span>style<span class="token punctuation">.</span>fontSize <span class="token operator">=</span> fontSize <span class="token operator">+</span> <span class="token string">'px'</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><h2 id="global-scss和reset-scss设置"><a href="#global-scss和reset-scss设置" class="header-anchor">#</a> global.scss和reset.scss设置</h2> <p>引入reset.css</p> <div class="language-css extra-class"><pre class="language-css"><code><span class="token comment">/* http://meyerweb.com/eric/tools/css/reset/ 
   v2.0 | 20110126
   License: none (public domain)
*/</span>

<span class="token selector">html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed, 
figure, figcaption, footer, header, hgroup, 
menu, nav, output, ruby, section, summary,
time, mark, audio, video</span> <span class="token punctuation">{</span>
	<span class="token property">margin</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span>
	<span class="token property">padding</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span>
	<span class="token property">border</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span>
	<span class="token property">font-size</span><span class="token punctuation">:</span> 100%<span class="token punctuation">;</span>
	<span class="token property">font</span><span class="token punctuation">:</span> inherit<span class="token punctuation">;</span>
	<span class="token property">vertical-align</span><span class="token punctuation">:</span> baseline<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">/* HTML5 display-role reset for older browsers */</span>
<span class="token selector">article, aside, details, figcaption, figure, 
footer, header, hgroup, menu, nav, section</span> <span class="token punctuation">{</span>
	<span class="token property">display</span><span class="token punctuation">:</span> block<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">body</span> <span class="token punctuation">{</span>
	<span class="token property">line-height</span><span class="token punctuation">:</span> 1<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">ol, ul</span> <span class="token punctuation">{</span>
	<span class="token property">list-style</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">blockquote, q</span> <span class="token punctuation">{</span>
	<span class="token property">quotes</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">blockquote:before, blockquote:after,
q:before, q:after</span> <span class="token punctuation">{</span>
	<span class="token property">content</span><span class="token punctuation">:</span> <span class="token string">''</span><span class="token punctuation">;</span>
	<span class="token property">content</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">table</span> <span class="token punctuation">{</span>
	<span class="token property">border-collapse</span><span class="token punctuation">:</span> collapse<span class="token punctuation">;</span>
	<span class="token property">border-spacing</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">html, body</span> <span class="token punctuation">{</span>
  <span class="token property">width</span><span class="token punctuation">:</span> 100%<span class="token punctuation">;</span>
  <span class="token property">height</span><span class="token punctuation">:</span> 100%<span class="token punctuation">;</span>
  <span class="token comment">/* 设置或检索是否允许用户选中文本，这里设置为否 */</span>
  <span class="token property">user-select</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span>
  <span class="token property">overflow</span><span class="token punctuation">:</span> hidden<span class="token punctuation">;</span>
  <span class="token property">font-family</span><span class="token punctuation">:</span> <span class="token string">'Segoe UI'</span><span class="token punctuation">,</span> Tahoma<span class="token punctuation">,</span> Geneva<span class="token punctuation">,</span> Verdana<span class="token punctuation">,</span> sans-serif<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><p>设置global.scss</p> <div class="language-scss extra-class"><pre class="language-scss"><code><span class="token keyword">@import</span> <span class="token string">'./reset.scss'</span><span class="token punctuation">;</span>

<span class="token property"><span class="token variable">$ratio</span></span><span class="token punctuation">:</span> 375 <span class="token operator">/</span> 10<span class="token punctuation">;</span>

<span class="token comment">// 将px转成rem</span>
<span class="token keyword">@function</span> <span class="token function">px2rem</span><span class="token punctuation">(</span><span class="token variable">$px</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">@return</span> <span class="token variable">$px</span> <span class="token operator">/</span> <span class="token variable">$ratio</span> <span class="token operator">+</span> rem<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><h2 id="vuex-vue-devtool"><a href="#vuex-vue-devtool" class="header-anchor">#</a> vuex+vue-devtool</h2> <p>Vuex 是专门为 Vue.js 设计的状态管理库，以利用 Vue.js 的细粒度数据响应机制来进行高效的状态更新，这里我们先来简单回顾下Vuex。</p> <p>store/index.js</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">import</span> Vue <span class="token keyword">from</span> <span class="token string">'vue'</span>
<span class="token keyword">import</span> Vuex <span class="token keyword">from</span> <span class="token string">'vuex'</span>

Vue<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>Vuex<span class="token punctuation">)</span>

<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">new</span> <span class="token class-name">Vuex<span class="token punctuation">.</span>Store</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  state<span class="token operator">:</span> <span class="token punctuation">{</span>
    count<span class="token operator">:</span> <span class="token number">1</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  mutations<span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token function">increment</span> <span class="token punctuation">(</span><span class="token parameter">state</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      state<span class="token punctuation">.</span>count<span class="token operator">++</span>
      console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>state<span class="token punctuation">.</span>count<span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  actions<span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token function">increment</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> commit <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token function">commit</span><span class="token punctuation">(</span><span class="token string">'increment'</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  modules<span class="token operator">:</span> <span class="token punctuation">{</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><p>App.vue</p> <div class="language-html extra-class"><pre class="language-html"><code>...
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script"><span class="token language-javascript">
<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token punctuation">{</span>
  <span class="token function">mounted</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
      <span class="token comment">// this.$store.commit('increment')</span>
      <span class="token keyword">this</span><span class="token punctuation">.</span>$store<span class="token punctuation">.</span><span class="token function">dispatch</span><span class="token punctuation">(</span><span class="token string">'increment'</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token number">3000</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>
...
</code></pre></div><p>上面这样使用vuex不好</p> <p>/store/modules/book.js</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> book <span class="token operator">=</span> <span class="token punctuation">{</span>
  state<span class="token operator">:</span> <span class="token punctuation">{</span>
    count<span class="token operator">:</span> <span class="token number">1</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  mutations<span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token function">increment</span> <span class="token punctuation">(</span><span class="token parameter">state</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      state<span class="token punctuation">.</span>count<span class="token operator">++</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  actions<span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token function">increment</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> commit <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token comment">// 返回的是一个promise，可以链式调用</span>
      <span class="token keyword">return</span> <span class="token function">commit</span><span class="token punctuation">(</span><span class="token string">'increment'</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">export</span> <span class="token keyword">default</span> book
</code></pre></div><p>/store/index.js</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">import</span> Vue <span class="token keyword">from</span> <span class="token string">'vue'</span>
<span class="token keyword">import</span> Vuex <span class="token keyword">from</span> <span class="token string">'vuex'</span>
<span class="token keyword">import</span> book <span class="token keyword">from</span> <span class="token string">'./modules/book'</span>

Vue<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>Vuex<span class="token punctuation">)</span>

<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">new</span> <span class="token class-name">Vuex<span class="token punctuation">.</span>Store</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  modules<span class="token operator">:</span> <span class="token punctuation">{</span>
    book
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><p>App.vue</p> <div class="language-vue extra-class"><pre class="language-vue"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>template</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>book<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>text<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>hello world<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>template</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script"><span class="token language-javascript">
<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token punctuation">{</span>
  <span class="token function">mounted</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
      <span class="token comment">// this.$store.commit('increment')</span>
      <span class="token keyword">this</span><span class="token punctuation">.</span>$store<span class="token punctuation">.</span><span class="token function">dispatch</span><span class="token punctuation">(</span><span class="token string">'increment'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>$store<span class="token punctuation">.</span>state<span class="token punctuation">.</span>book<span class="token punctuation">.</span>count<span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token number">3000</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><h2 id="搭建静态资源服务器"><a href="#搭建静态资源服务器" class="header-anchor">#</a> 搭建静态资源服务器</h2> <p>nginx占用内存少、运行速度快、并发的能力比较强</p> <p>启动 nginx 服务：</p> <div class="language-sh extra-class"><pre class="language-sh"><code><span class="token function">sudo</span> nginx
</code></pre></div><p>重启 nginx 服务：</p> <div class="language-sh extra-class"><pre class="language-sh"><code><span class="token function">sudo</span> nginx -s reload
</code></pre></div><p>停止nginx服务：</p> <div class="language-sh extra-class"><pre class="language-sh"><code><span class="token function">sudo</span> nginx -s stop
</code></pre></div><p>检查配置文件是否存在语法错误：</p> <div class="language-sh extra-class"><pre class="language-sh"><code><span class="token function">sudo</span> nginx -t
</code></pre></div><p>nginx配置文件存放目录：<code>/usr/local/etc/nginx/</code></p> <p>打开nginx配置文件并加入如下代码：</p> <div class="language-sh extra-class"><pre class="language-sh"><code>server <span class="token punctuation">{</span>
  listen <span class="token number">8083</span><span class="token punctuation">;</span>
  server_name ebook_assets<span class="token punctuation">;</span>
  root /Users/sun/Desktop/ebook_assets<span class="token punctuation">;</span>
  <span class="token comment"># Nginx默认是不允许列出整个目录的。如需此功能，打开nginx.conf文件或你要启用目录浏览虚拟主机的配置文件，在server或location 段里添加上autoindex on;来启用目录浏览</span>
  autoindex on<span class="token punctuation">;</span>
  <span class="token comment"># 处理跨域</span>
  location / <span class="token punctuation">{</span>
    add_header Access-Control-Allow-Origin *<span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token comment"># 不做缓存，适用于文件经常变动</span>
  add_header Cache-Control <span class="token string">&quot;no-cache, must-revalidate&quot;</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><p>配置完成后的nginx文件</p> <div class="language-sh extra-class"><pre class="language-sh"><code><span class="token comment">#user  nobody;</span>
worker_processes  <span class="token number">1</span><span class="token punctuation">;</span>

<span class="token comment">#error_log  logs/error.log;</span>
<span class="token comment">#error_log  logs/error.log  notice;</span>
<span class="token comment">#error_log  logs/error.log  info;</span>

<span class="token comment">#pid        logs/nginx.pid;</span>


events <span class="token punctuation">{</span>
    worker_connections  <span class="token number">1024</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>


http <span class="token punctuation">{</span>
    include       mime.types<span class="token punctuation">;</span>
    default_type  application/octet-stream<span class="token punctuation">;</span>

    <span class="token comment">#log_format  main  '$remote_addr - $remote_user [$time_local] &quot;$request&quot; '</span>
    <span class="token comment">#                  '$status $body_bytes_sent &quot;$http_referer&quot; '</span>
    <span class="token comment">#                  '&quot;$http_user_agent&quot; &quot;$http_x_forwarded_for&quot;';</span>

    <span class="token comment">#access_log  logs/access.log  main;</span>

    sendfile        on<span class="token punctuation">;</span>
    <span class="token comment">#tcp_nopush     on;</span>

    <span class="token comment">#keepalive_timeout  0;</span>
    keepalive_timeout  <span class="token number">65</span><span class="token punctuation">;</span>

    <span class="token comment">#gzip  on;</span>
    include /usr/local/etc/nginx/myconf/*.conf<span class="token punctuation">;</span>
    server <span class="token punctuation">{</span>
        listen       <span class="token number">8080</span><span class="token punctuation">;</span>
        server_name  localhost<span class="token punctuation">;</span>

        <span class="token comment">#charset koi8-r;</span>

        <span class="token comment">#access_log  logs/host.access.log  main;</span>

        location / <span class="token punctuation">{</span>
            root   html<span class="token punctuation">;</span>
            index  index.html index.htm<span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

        <span class="token comment">#error_page  404              /404.html;</span>

        <span class="token comment"># redirect server error pages to the static page /50x.html</span>
        <span class="token comment">#</span>
        error_page   <span class="token number">500</span> <span class="token number">502</span> <span class="token number">503</span> <span class="token number">504</span>  /50x.html<span class="token punctuation">;</span>
        location <span class="token operator">=</span> /50x.html <span class="token punctuation">{</span>
            root   html<span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

        <span class="token comment"># proxy the PHP scripts to Apache listening on 127.0.0.1:80</span>
        <span class="token comment">#</span>
        <span class="token comment">#location ~ \.php$ {</span>
        <span class="token comment">#    proxy_pass   http://127.0.0.1;</span>
        <span class="token comment">#}</span>

        <span class="token comment"># pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000</span>
        <span class="token comment">#</span>
        <span class="token comment">#location ~ \.php$ {</span>
        <span class="token comment">#    root           html;</span>
        <span class="token comment">#    fastcgi_pass   127.0.0.1:9000;</span>
        <span class="token comment">#    fastcgi_index  index.php;</span>
        <span class="token comment">#    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;</span>
        <span class="token comment">#    include        fastcgi_params;</span>
        <span class="token comment">#}</span>

        <span class="token comment"># deny access to .htaccess files, if Apache's document root</span>
        <span class="token comment"># concurs with nginx's one</span>
        <span class="token comment">#</span>
        <span class="token comment">#location ~ /\.ht {</span>
        <span class="token comment">#    deny  all;</span>
        <span class="token comment">#}</span>
    <span class="token punctuation">}</span>

    <span class="token comment"># ebook</span>
    server <span class="token punctuation">{</span>
      listen <span class="token number">8083</span><span class="token punctuation">;</span>
      server_name ebook_assets<span class="token punctuation">;</span>
      root /Users/sun/Desktop/ebook_assets<span class="token punctuation">;</span>
      <span class="token comment"># Nginx默认是不允许列出整个目录的。如需此功能，打开nginx.conf文件或你要启用目录浏览虚拟主机的配置文件，在server或location 段里添加上autoindex on;来启用目录浏览</span>
      autoindex on<span class="token punctuation">;</span>
      <span class="token comment"># 处理跨域</span>
      location / <span class="token punctuation">{</span>
        add_header Access-Control-Allow-Origin *<span class="token punctuation">;</span>
      <span class="token punctuation">}</span>
      <span class="token comment"># 不做缓存，适用于文件经常变动</span>
      add_header Cache-Control <span class="token string">&quot;no-cache, must-revalidate&quot;</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token comment"># another virtual host using mix of IP-, name-, and port-based configuration</span>
    <span class="token comment">#</span>
    <span class="token comment">#server {</span>
    <span class="token comment">#    listen       8000;</span>
    <span class="token comment">#    listen       somename:8080;</span>
    <span class="token comment">#    server_name  somename  alias  another.alias;</span>

    <span class="token comment">#    location / {</span>
    <span class="token comment">#        root   html;</span>
    <span class="token comment">#        index  index.html index.htm;</span>
    <span class="token comment">#    }</span>
    <span class="token comment">#}</span>


    <span class="token comment"># HTTPS server</span>
    <span class="token comment">#</span>
    <span class="token comment">#server {</span>
    <span class="token comment">#    listen       443 ssl;</span>
    <span class="token comment">#    server_name  localhost;</span>

    <span class="token comment">#    ssl_certificate      cert.pem;</span>
    <span class="token comment">#    ssl_certificate_key  cert.key;</span>

    <span class="token comment">#    ssl_session_cache    shared:SSL:1m;</span>
    <span class="token comment">#    ssl_session_timeout  5m;</span>

    <span class="token comment">#    ssl_ciphers  HIGH:!aNULL:!MD5;</span>
    <span class="token comment">#    ssl_prefer_server_ciphers  on;</span>

    <span class="token comment">#    location / {</span>
    <span class="token comment">#        root   html;</span>
    <span class="token comment">#        index  index.html index.htm;</span>
    <span class="token comment">#    }</span>
    <span class="token comment">#}</span>
    include servers/*<span class="token punctuation">;</span>
    include /Users/sun/upload/upload.conf<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><h2 id="阅读器需求分析"><a href="#阅读器需求分析" class="header-anchor">#</a> 阅读器需求分析</h2> <p>首先实现阅读器的解析和渲染之后开发字体、字号、主题设置功能，之后开发阅读进度和目录功能，之后做一个全文搜索和加书签功能、添加页眉、页脚，之后实现分页功能。</p> <h2 id="阅读器的解析和渲染"><a href="#阅读器的解析和渲染" class="header-anchor">#</a> 阅读器的解析和渲染</h2> <p>动态路由</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">import</span> Vue <span class="token keyword">from</span> <span class="token string">'vue'</span>
<span class="token keyword">import</span> VueRouter <span class="token keyword">from</span> <span class="token string">'vue-router'</span>

Vue<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>VueRouter<span class="token punctuation">)</span>

<span class="token keyword">const</span> routes <span class="token operator">=</span> <span class="token punctuation">[</span>
  <span class="token punctuation">{</span>
    path<span class="token operator">:</span> <span class="token string">'/'</span><span class="token punctuation">,</span>
    redirect<span class="token operator">:</span> <span class="token string">'/ebook'</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">{</span>
    path<span class="token operator">:</span> <span class="token string">'/ebook'</span><span class="token punctuation">,</span>
    <span class="token function-variable function">component</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token keyword">import</span><span class="token punctuation">(</span><span class="token string">'../views/ebook/index.vue'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
    <span class="token comment">// 动态路由</span>
    children<span class="token operator">:</span> <span class="token punctuation">[</span>
      <span class="token punctuation">{</span>
        path<span class="token operator">:</span> <span class="token string">':fileName'</span><span class="token punctuation">,</span>
        <span class="token function-variable function">component</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token keyword">import</span><span class="token punctuation">(</span><span class="token string">'../components/ebook/EbookReader.vue'</span><span class="token punctuation">)</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">]</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">]</span>

<span class="token keyword">const</span> router <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">VueRouter</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  routes
<span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token keyword">export</span> <span class="token keyword">default</span> router
</code></pre></div><p>获取动态路由参数</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">this</span><span class="token punctuation">.</span>$route<span class="token punctuation">.</span>params<span class="token punctuation">.</span>fileName
</code></pre></div><h2 id="阅读器翻页功能实现"><a href="#阅读器翻页功能实现" class="header-anchor">#</a> 阅读器翻页功能实现</h2> <p>电子书epub对象的实现原理是使用的iframe，怎么向iframe绑定我们自己的事件呢？epubjs提供了on方法，我们可以通过on方法绑定事件</p> <div class="language-vue extra-class"><pre class="language-vue"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script"><span class="token language-javascript">
  <span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token punctuation">{</span>
    <span class="token operator">...</span>
    methods<span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token function">prevPage</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>reader<span class="token punctuation">)</span> <span class="token keyword">this</span><span class="token punctuation">.</span>reader<span class="token punctuation">.</span><span class="token function">prev</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token function">nextPage</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>reader<span class="token punctuation">)</span> <span class="token keyword">this</span><span class="token punctuation">.</span>reader<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token function">toggleTitleAndMenu</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token function">initEpub</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">const</span> url <span class="token operator">=</span> <span class="token string">'http://192.168.0.103:8083/epub/'</span> <span class="token operator">+</span> <span class="token keyword">this</span><span class="token punctuation">.</span>fileName <span class="token operator">+</span> <span class="token string">'.epub'</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>book <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Epub</span><span class="token punctuation">(</span>url<span class="token punctuation">)</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>reader <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>book<span class="token punctuation">.</span><span class="token function">renderTo</span><span class="token punctuation">(</span><span class="token string">'reader'</span><span class="token punctuation">,</span> <span class="token punctuation">{</span>
          width<span class="token operator">:</span> innerWidth<span class="token punctuation">,</span>
          height<span class="token operator">:</span> innerHeight
        <span class="token punctuation">}</span><span class="token punctuation">)</span>

        <span class="token keyword">this</span><span class="token punctuation">.</span>reader<span class="token punctuation">.</span><span class="token function">display</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>reader<span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">'touchstart'</span><span class="token punctuation">,</span> <span class="token parameter">e</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
          <span class="token keyword">this</span><span class="token punctuation">.</span>touchStartX <span class="token operator">=</span> e<span class="token punctuation">.</span>changedTouches<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>clientX
          <span class="token keyword">this</span><span class="token punctuation">.</span>timeStamp <span class="token operator">=</span> e<span class="token punctuation">.</span>timeStamp
        <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">'touchend'</span><span class="token punctuation">,</span> <span class="token parameter">e</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
          e<span class="token punctuation">.</span><span class="token function">preventDefault</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
          e<span class="token punctuation">.</span><span class="token function">stopPropagation</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
          <span class="token keyword">this</span><span class="token punctuation">.</span>offsetX <span class="token operator">=</span> e<span class="token punctuation">.</span>changedTouches<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>clientX <span class="token operator">-</span> <span class="token keyword">this</span><span class="token punctuation">.</span>touchStartX
          <span class="token keyword">this</span><span class="token punctuation">.</span>time <span class="token operator">=</span> e<span class="token punctuation">.</span>timeStamp <span class="token operator">-</span> <span class="token keyword">this</span><span class="token punctuation">.</span>timeStamp
          <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>time <span class="token operator">&lt;</span> <span class="token number">500</span> <span class="token operator">&amp;&amp;</span> <span class="token keyword">this</span><span class="token punctuation">.</span>offsetX <span class="token operator">&gt;</span> <span class="token number">40</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">prevPage</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
          <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>time <span class="token operator">&lt;</span> <span class="token number">500</span> <span class="token operator">&amp;&amp;</span> <span class="token keyword">this</span><span class="token punctuation">.</span>offsetX <span class="token operator">&lt;</span> <span class="token operator">-</span><span class="token number">40</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">nextPage</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
          <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
            <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">toggleTitleAndMenu</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
          <span class="token punctuation">}</span>
        <span class="token punctuation">}</span><span class="token punctuation">)</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
    <span class="token operator">...</span>
  <span class="token punctuation">}</span>
</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><p>上面我们分别绑定了touchstart和touchend事件，通过这两个事件来实现电子书的手势操作。changedTouches会有一个clientX属性，timeStamp判断用户操作时长，时长过长则不做操作。</p> <p>翻页时浏览器控制台有时会输出<code>Unable to preventDefault inside passive event listener invocation.</code></p> <div class="language-js extra-class"><pre class="language-js"><code>由于浏览器必须要在执行事件处理函数之后，才能知道有没有掉用过 <span class="token function">preventDefault</span><span class="token punctuation">(</span><span class="token punctuation">)</span> ，这就导致了浏览器不能及时响应滚动，略有延迟。
 
所以为了让页面滚动的效果如丝般顺滑，从 chrome56 开始，在 window、document 和 body 上注册的 touchstart 和 touchmove 事件处理函数，会默认为是 passive<span class="token operator">:</span> <span class="token boolean">true</span>。浏览器忽略 <span class="token function">preventDefault</span><span class="token punctuation">(</span><span class="token punctuation">)</span> 就可以第一时间滚动了。
 
举例：
wnidow<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'touchmove'</span><span class="token punctuation">,</span> func<span class="token punctuation">)</span> 效果和下面一句一样
wnidow<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'touchmove'</span><span class="token punctuation">,</span> func<span class="token punctuation">,</span> <span class="token punctuation">{</span> passive<span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><p>https://www.freesion.com/article/59134650/</p> <h2 id="标题栏和菜单栏实现"><a href="#标题栏和菜单栏实现" class="header-anchor">#</a> 标题栏和菜单栏实现</h2> <h2 id="字号设置ui实现"><a href="#字号设置ui实现" class="header-anchor">#</a> 字号设置UI实现</h2> <h2 id="字号设置功能实现"><a href="#字号设置功能实现" class="header-anchor">#</a> 字号设置功能实现</h2> <p>使用<code>this.currentBook.rendition.themes.fontSize(16)</code>给电子书设置字体时不生效，打印<code>this.currentBook.rendition.themes.fontSize</code>，控制台输出</p> <div class="language-js extra-class"><pre class="language-js"><code>ƒ <span class="token function">fontSize</span> <span class="token punctuation">(</span><span class="token parameter">size</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	<span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">override</span><span class="token punctuation">(</span><span class="token string">&quot;font-size&quot;</span><span class="token punctuation">,</span> size<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><p>将传入的fontSize改为'16px'即可。</p> <h2 id="字体设置弹窗ui实现"><a href="#字体设置弹窗ui实现" class="header-anchor">#</a> 字体设置弹窗UI实现</h2> <h2 id="字体设置弹窗功能实现"><a href="#字体设置弹窗功能实现" class="header-anchor">#</a> 字体设置弹窗功能实现</h2> <p>设置字体</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// EbookSettingFont.vue</span>
<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token punctuation">{</span>
  <span class="token comment">// ...</span>
  methods<span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token comment">// ...</span>
    <span class="token function">setFontFamily</span> <span class="token punctuation">(</span><span class="token parameter">font</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setDefaultFontFamily</span><span class="token punctuation">(</span>font<span class="token punctuation">)</span>
      <span class="token keyword">this</span><span class="token punctuation">.</span>currentBook<span class="token punctuation">.</span>rendition<span class="token punctuation">.</span>themes<span class="token punctuation">.</span><span class="token function">font</span><span class="token punctuation">(</span>font<span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
    <span class="token comment">// ...</span>
  <span class="token punctuation">}</span>
  <span class="token comment">// ...</span>
<span class="token punctuation">}</span>
</code></pre></div><p>这样设置并不会生效，因为阅读器的DOM是通过一个iframe实现的</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// EbookReader.vue</span>
<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token punctuation">{</span>
  <span class="token comment">// ...</span>
  methods<span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token comment">// ...</span>
    <span class="token function">initEpub</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token comment">// ...</span>
      <span class="token keyword">this</span><span class="token punctuation">.</span>rendition<span class="token punctuation">.</span>hooks<span class="token punctuation">.</span>content<span class="token punctuation">.</span><span class="token function">register</span><span class="token punctuation">(</span><span class="token parameter">contents</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
        Promise<span class="token punctuation">.</span><span class="token function">all</span><span class="token punctuation">(</span><span class="token punctuation">[</span>
          contents<span class="token punctuation">.</span><span class="token function">addStylesheet</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>process<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">VUE_APP_RES_URL</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">/fonts/daysOne.css</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">,</span>
          contents<span class="token punctuation">.</span><span class="token function">addStylesheet</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>process<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">VUE_APP_RES_URL</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">/fonts/tangerine.css</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">,</span>
          contents<span class="token punctuation">.</span><span class="token function">addStylesheet</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>process<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">VUE_APP_RES_URL</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">/fonts/montserrat.css</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">,</span>
          contents<span class="token punctuation">.</span><span class="token function">addStylesheet</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>process<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">VUE_APP_RES_URL</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">/fonts/cabin.css</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span>
        <span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span>
      <span class="token punctuation">}</span>
      <span class="token comment">// ...</span>
    <span class="token punctuation">}</span>
    <span class="token comment">// ...</span>
  <span class="token punctuation">}</span>
  <span class="token comment">// ...</span>
<span class="token punctuation">}</span>
<span class="token comment">// ...</span>
</code></pre></div><p>模式和环境变量 https://cli.vuejs.org/zh/guide/mode-and-env.html#%E6%A8%A1%E5%BC%8F</p> <h2 id="字号和字体设置离线存储"><a href="#字号和字体设置离线存储" class="header-anchor">#</a> 字号和字体设置离线存储</h2> <div class="language-sh extra-class"><pre class="language-sh"><code>cnpm i web-storage-cache -S
</code></pre></div><h2 id="字体设置标题国际化"><a href="#字体设置标题国际化" class="header-anchor">#</a> 字体设置标题国际化</h2> <h2 id="阅读器主题功能实现"><a href="#阅读器主题功能实现" class="header-anchor">#</a> 阅读器主题功能实现</h2> <h2 id="全局主题设置功能实现"><a href="#全局主题设置功能实现" class="header-anchor">#</a> 全局主题设置功能实现</h2> <p>动态切换全局样式的实现原理是给DOM动态添加或者删除css文件，css样式文件的引入是head标签下添加link标签</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">export</span> <span class="token keyword">function</span> <span class="token function">removeCssFile</span> <span class="token punctuation">(</span><span class="token parameter">href</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> link <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementsByTagName</span><span class="token punctuation">(</span><span class="token string">'link'</span><span class="token punctuation">)</span>

  <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">var</span> i <span class="token operator">=</span> link<span class="token punctuation">.</span>length<span class="token punctuation">;</span> i <span class="token operator">&gt;=</span> <span class="token number">0</span><span class="token punctuation">;</span> i<span class="token operator">--</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>link<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">&amp;&amp;</span> link<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">getAttribute</span><span class="token punctuation">(</span><span class="token string">'href'</span><span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> link<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">getAttribute</span><span class="token punctuation">(</span><span class="token string">'href'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">indexOf</span><span class="token punctuation">(</span>href<span class="token punctuation">)</span> <span class="token operator">!==</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      link<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">.</span>parentNode<span class="token punctuation">.</span><span class="token function">removeChild</span><span class="token punctuation">(</span>link<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">export</span> <span class="token keyword">function</span> <span class="token function">clearPreTheme</span> <span class="token punctuation">(</span><span class="token parameter">href</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> cssArr <span class="token operator">=</span> <span class="token punctuation">[</span>
    <span class="token string">'theme_eye.css'</span><span class="token punctuation">,</span> 
    <span class="token string">'theme_gold.css'</span><span class="token punctuation">,</span> 
    <span class="token string">'theme_night.css'</span><span class="token punctuation">,</span>
    <span class="token string">'theme_default.css'</span>
  <span class="token punctuation">]</span>

  cssArr<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span>removeCssFile<span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre></div><h2 id="阅读进度功能实现-进度面板-分页逻辑"><a href="#阅读进度功能实现-进度面板-分页逻辑" class="header-anchor">#</a> 阅读进度功能实现（进度面板+分页逻辑）</h2> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// ...</span>
<span class="token comment">// 分页</span>
<span class="token function">initPaging</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span>book<span class="token punctuation">.</span>ready<span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>book<span class="token punctuation">.</span>locations<span class="token punctuation">.</span><span class="token function">generate</span><span class="token punctuation">(</span><span class="token number">750</span> <span class="token operator">*</span> <span class="token punctuation">(</span>window<span class="token punctuation">.</span>innerWidth <span class="token operator">/</span> <span class="token number">375</span><span class="token punctuation">)</span> <span class="token operator">*</span> <span class="token punctuation">(</span><span class="token function">getFontSize</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>fileName<span class="token punctuation">)</span> <span class="token operator">/</span> <span class="token number">16</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">locations</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>locations<span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token comment">// ...</span>
</code></pre></div><p>epubcif是epub标准中的一个核心标准，用来做电子书的定位，可以定位电子书中任何一个位置</p> <h2 id="阅读进度功能实现-进度拖动功能"><a href="#阅读进度功能实现-进度拖动功能" class="header-anchor">#</a> 阅读进度功能实现（进度拖动功能）</h2> <div class="language-css extra-class"><pre class="language-css"><code><span class="token property">-webkit-appearance</span> <span class="token punctuation">:</span> none <span class="token punctuation">;</span>
</code></pre></div><p>移除原生控件样式。</p> <h2 id="阅读进度功能实现-上下章节切换功能"><a href="#阅读进度功能实现-上下章节切换功能" class="header-anchor">#</a> 阅读进度功能实现（上下章节切换功能）</h2> <div class="language-js extra-class"><pre class="language-js"><code><span class="token function">prevSection</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>section <span class="token operator">&gt;</span> <span class="token number">0</span> <span class="token operator">&amp;&amp;</span> <span class="token keyword">this</span><span class="token punctuation">.</span>bookAvailable<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setSection</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>section <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>displaySection<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">catch</span><span class="token punctuation">(</span><span class="token parameter">err</span> <span class="token operator">=&gt;</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token function">nextSection</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>section <span class="token operator">&lt;</span> <span class="token keyword">this</span><span class="token punctuation">.</span>currentBook<span class="token punctuation">.</span>spine<span class="token punctuation">.</span>length <span class="token operator">-</span> <span class="token number">1</span> <span class="token operator">&amp;&amp;</span> <span class="token keyword">this</span><span class="token punctuation">.</span>bookAvailable<span class="token punctuation">)</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setSection</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>section <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>displaySection<span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token function">displaySection</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> sectionInfo <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>currentBook<span class="token punctuation">.</span><span class="token function">section</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>section<span class="token punctuation">)</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>sectionInfo <span class="token operator">&amp;&amp;</span> sectionInfo<span class="token punctuation">.</span>href<span class="token punctuation">)</span> <span class="token keyword">this</span><span class="token punctuation">.</span>currentBook<span class="token punctuation">.</span>rendition<span class="token punctuation">.</span><span class="token function">display</span><span class="token punctuation">(</span>sectionInfo<span class="token punctuation">.</span>href<span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre></div><h2 id="阅读进度功能实现-章节切换和进度同步"><a href="#阅读进度功能实现-章节切换和进度同步" class="header-anchor">#</a> 阅读进度功能实现（章节切换和进度同步）</h2> <p>章节标题超出显示省略号</p> <div class="language-css extra-class"><pre class="language-css"><code><span class="token selector">.section</span> <span class="token punctuation">{</span>
  <span class="token property">text-overflow</span><span class="token punctuation">:</span> ellipsis<span class="token punctuation">;</span>
  <span class="token property">overflow</span><span class="token punctuation">:</span> hidden<span class="token punctuation">;</span>
  <span class="token property">white-space</span><span class="token punctuation">:</span> nowrap<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><p>刷新位置</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token function">refreshContent</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> curLocation <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>currentBook<span class="token punctuation">.</span>rendition<span class="token punctuation">.</span><span class="token function">currentLocation</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>curLocation<span class="token punctuation">)</span>
  <span class="token keyword">const</span> cfi <span class="token operator">=</span> <span class="token punctuation">(</span>curLocation<span class="token punctuation">.</span>start <span class="token operator">&amp;&amp;</span> curLocation<span class="token punctuation">.</span>start<span class="token punctuation">.</span>cfi<span class="token punctuation">)</span> <span class="token operator">||</span> <span class="token string">''</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>cfi<span class="token punctuation">)</span> <span class="token keyword">return</span>
  <span class="token keyword">const</span> progress <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>currentBook<span class="token punctuation">.</span>locations<span class="token punctuation">.</span><span class="token function">percentageFromCfi</span><span class="token punctuation">(</span>cfi<span class="token punctuation">)</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setProgress</span><span class="token punctuation">(</span>Math<span class="token punctuation">.</span><span class="token function">floor</span><span class="token punctuation">(</span>progress <span class="token operator">*</span> <span class="token number">100</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre></div><p>log输出如下</p> <p><img src="/assets/img/1.7a92ea29.png" alt=""></p> <p>获取章节名称</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token function">sectionName</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>section<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> section <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>currentBook<span class="token punctuation">.</span><span class="token function">section</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>section<span class="token punctuation">)</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>currentBook<span class="token punctuation">.</span>navigation<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>section<span class="token punctuation">.</span>href<span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>section <span class="token operator">&amp;&amp;</span> section<span class="token punctuation">.</span>href<span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>currentBook<span class="token punctuation">.</span>navigation<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>section<span class="token punctuation">.</span>href<span class="token punctuation">)</span><span class="token punctuation">.</span>label
    <span class="token keyword">return</span> <span class="token string">'未知章节'</span>
  <span class="token punctuation">}</span>
  <span class="token keyword">return</span> <span class="token string">'未知章节'</span>
<span class="token punctuation">}</span>
</code></pre></div><p>log输出如下，label属性的值代表当前正在看的章节名称。</p> <p><img src="/assets/img/2.ca108274.png" alt=""></p> <h2 id="阅读进度功能实现-保存阅读进度功能"><a href="#阅读进度功能实现-保存阅读进度功能" class="header-anchor">#</a> 阅读进度功能实现（保存阅读进度功能）</h2> <h2 id="目录功能实现-目录浮出效果"><a href="#目录功能实现-目录浮出效果" class="header-anchor">#</a> 目录功能实现（目录浮出效果）</h2> <h2 id="目录功能实现-tab选项切换和搜索效果"><a href="#目录功能实现-tab选项切换和搜索效果" class="header-anchor">#</a> 目录功能实现（Tab选项切换和搜索效果）</h2> <div class="language-css extra-class"><pre class="language-css"><code><span class="token property">flex</span><span class="token punctuation">:</span> 0 0 <span class="token function">px2rem</span><span class="token punctuation">(</span>48<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p>书籍搜索框底部tab切换</p> <div class="language-vue extra-class"><pre class="language-vue"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>component</span> <span class="token attr-name">:is</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>tab === 1 ? content : bookmark<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>component</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><p>搜索框样式</p> <div class="language-css extra-class"><pre class="language-css"><code><span class="token selector">.slide-contents-search-input</span> <span class="token punctuation">{</span>
  <span class="token property">flex</span><span class="token punctuation">:</span> 1<span class="token punctuation">;</span>
  <span class="token property">width</span><span class="token punctuation">:</span> 100%<span class="token punctuation">;</span>
  <span class="token property">height</span><span class="token punctuation">:</span> <span class="token function">px2rem</span><span class="token punctuation">(</span>32<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">font-size</span><span class="token punctuation">:</span> <span class="token function">px2rem</span><span class="token punctuation">(</span>14<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">background</span><span class="token punctuation">:</span> transparent<span class="token punctuation">;</span>
  <span class="token property">border</span><span class="token punctuation">:</span> none<span class="token selector">;
  &amp;:focus</span> <span class="token punctuation">{</span>
    <span class="token property">outline</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token selector">&amp;::-webkit-input-placeholder</span> <span class="token punctuation">{</span>
    <span class="token property">font-size</span><span class="token punctuation">:</span> <span class="token function">px2rem</span><span class="token punctuation">(</span>14<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token property">color</span><span class="token punctuation">:</span> #ccc<span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><h2 id="目录功能实现-图书内容布局"><a href="#目录功能实现-图书内容布局" class="header-anchor">#</a> 目录功能实现（图书内容布局）</h2> <div class="language-vue extra-class"><pre class="language-vue"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>img</span> <span class="token attr-name">v-lazy</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>cover<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
</code></pre></div><h2 id="目录功能实现-图书内容样式"><a href="#目录功能实现-图书内容样式" class="header-anchor">#</a> 目录功能实现（图书内容样式）</h2> <p><img src="/assets/img/3.9600eaaa.png" alt="">
可通过设置css: font-size:0;</p> <p>封装</p> <div class="language-scss extra-class"><pre class="language-scss"><code><span class="token comment">// 显示省略号</span>
<span class="token keyword">@mixin</span> <span class="token selector">ellipsis </span><span class="token punctuation">{</span>
  <span class="token property">text-overflow</span><span class="token punctuation">:</span> ellipsis<span class="token punctuation">;</span>
  <span class="token property">overflow</span><span class="token punctuation">:</span> hidden<span class="token punctuation">;</span>
  <span class="token property">white-space</span><span class="token punctuation">:</span> nowrap<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">// 指定换行数并显示省略号</span>
<span class="token keyword">@mixin</span> <span class="token function">ellipsis2</span><span class="token punctuation">(</span><span class="token variable">$line</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token property">display</span><span class="token punctuation">:</span> -webkit-box<span class="token punctuation">;</span>
  <span class="token property">-webkit-box-orient</span><span class="token punctuation">:</span> vertical<span class="token punctuation">;</span>
  <span class="token property">-webkit-line-clamp</span><span class="token punctuation">:</span> <span class="token variable">$line</span><span class="token punctuation">;</span>
  <span class="token comment">// break-all </span>
  <span class="token comment">// keep-all</span>
  <span class="token property">word-break</span><span class="token punctuation">:</span> keep-all<span class="token punctuation">;</span>
  <span class="token property">white-space</span><span class="token punctuation">:</span> normal<span class="token punctuation">;</span>
  <span class="token property">overflow</span><span class="token punctuation">:</span> hidden<span class="token punctuation">;</span>
  <span class="token property">text-overflow</span><span class="token punctuation">:</span> ellipsis<span class="token punctuation">;</span>
  <span class="token property">overflow-wrap</span><span class="token punctuation">:</span> break-word<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><p>使用</p> <div class="language-scss extra-class"><pre class="language-scss"><code><span class="token selector">.slide-contents-book-author-text </span><span class="token punctuation">{</span>
  <span class="token keyword">@include</span> <span class="token function">ellipsis2</span><span class="token punctuation">(</span>1<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token selector">.slide-contents-item-label </span><span class="token punctuation">{</span>
  <span class="token keyword">@include</span> ellipsis<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><h2 id="目录功能实现-目录数据结构开发"><a href="#目录功能实现-目录数据结构开发" class="header-anchor">#</a> 目录功能实现（目录数据结构开发）</h2> <div class="language-js extra-class"><pre class="language-js"><code>book<span class="token punctuation">.</span>loaded<span class="token punctuation">.</span>navigation<span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">nav</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'nav'</span><span class="token punctuation">,</span> nav<span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><p>输出如下
<img src="/assets/img/4.2e98fadc.png" alt=""></p> <h2 id="目录功能实现-多级目录功能"><a href="#目录功能实现-多级目录功能" class="header-anchor">#</a> 目录功能实现（多级目录功能）</h2> <p>将下面数组整理成一个一维度数组</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> arr <span class="token operator">=</span> <span class="token punctuation">[</span>
    <span class="token punctuation">{</span>
        id<span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span>
        arr<span class="token operator">:</span> <span class="token punctuation">[</span>
            <span class="token punctuation">{</span>
                id<span class="token operator">:</span><span class="token number">2</span><span class="token punctuation">,</span>
                arr<span class="token operator">:</span><span class="token punctuation">[</span>
                    <span class="token punctuation">{</span>
                        id<span class="token operator">:</span><span class="token number">3</span><span class="token punctuation">,</span>
                        arr<span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span>
                    <span class="token punctuation">}</span>
                <span class="token punctuation">]</span>
            <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span>
                id<span class="token operator">:</span> <span class="token number">4</span><span class="token punctuation">,</span>
                arr<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>
            <span class="token punctuation">}</span>
        <span class="token punctuation">]</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">{</span>
        id<span class="token operator">:</span> <span class="token number">5</span><span class="token punctuation">,</span>
        arr<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">]</span>

<span class="token keyword">function</span> <span class="token function">flatten</span> <span class="token punctuation">(</span><span class="token parameter">arr</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">concat</span><span class="token punctuation">(</span><span class="token operator">...</span>arr<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token parameter">item</span> <span class="token operator">=&gt;</span> <span class="token punctuation">[</span>item<span class="token punctuation">,</span> <span class="token operator">...</span><span class="token function">flatten</span><span class="token punctuation">(</span>item<span class="token punctuation">.</span>subitems<span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre></div><div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">export</span> <span class="token keyword">function</span> <span class="token function">addLevel</span> <span class="token punctuation">(</span><span class="token parameter">nav<span class="token punctuation">,</span> item<span class="token punctuation">,</span> level <span class="token operator">=</span> <span class="token number">0</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> <span class="token operator">!</span>item<span class="token punctuation">.</span>parent <span class="token operator">?</span> level <span class="token operator">:</span> <span class="token function">addLevel</span><span class="token punctuation">(</span>nav<span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token parameter">p</span> <span class="token operator">=&gt;</span> p<span class="token punctuation">.</span>id <span class="token operator">===</span> item<span class="token punctuation">.</span>parent<span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token operator">++</span>level<span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre></div><p>解决移动端滚动卡顿问题</p> <div class="language-css extra-class"><pre class="language-css"><code><span class="token property">-webkit-overflow-scrolling</span><span class="token punctuation">:</span> touch<span class="token punctuation">;</span>
</code></pre></div><div class="language-js extra-class"><pre class="language-js"><code><span class="token function">sectionName</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>section<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> section <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>currentBook<span class="token punctuation">.</span><span class="token function">section</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>section<span class="token punctuation">)</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'dfasd'</span><span class="token punctuation">,</span> <span class="token keyword">this</span><span class="token punctuation">.</span>currentBook<span class="token punctuation">.</span>navigation<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>section<span class="token punctuation">.</span>href<span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>section <span class="token operator">&amp;&amp;</span> section<span class="token punctuation">.</span>href <span class="token operator">&amp;&amp;</span> <span class="token keyword">this</span><span class="token punctuation">.</span>currentBook <span class="token operator">&amp;&amp;</span> <span class="token keyword">this</span><span class="token punctuation">.</span>currentBook<span class="token punctuation">.</span>navigation<span class="token punctuation">)</span>
    <span class="token comment">// 这个get方法只能获取一级目录，无法获取更深层次的方法 </span>
    <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>currentBook<span class="token punctuation">.</span>navigation<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>section<span class="token punctuation">.</span>href<span class="token punctuation">)</span><span class="token punctuation">.</span>label
    <span class="token keyword">return</span> <span class="token string">'未知章节'</span>
  <span class="token punctuation">}</span>
  <span class="token keyword">return</span> <span class="token string">'未知章节'</span>
<span class="token punctuation">}</span>

<span class="token comment">// 修改如下</span>
<span class="token function">sectionName</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>section <span class="token operator">&amp;&amp;</span> <span class="token keyword">this</span><span class="token punctuation">.</span>navigation <span class="token operator">?</span> <span class="token keyword">this</span><span class="token punctuation">.</span>navigation<span class="token punctuation">[</span><span class="token keyword">this</span><span class="token punctuation">.</span>section<span class="token punctuation">]</span><span class="token punctuation">.</span>label <span class="token operator">:</span> <span class="token string">'未知章节'</span>
<span class="token punctuation">}</span>
</code></pre></div><h2 id="全文搜索功能实现-搜索算法-数组降维"><a href="#全文搜索功能实现-搜索算法-数组降维" class="header-anchor">#</a> 全文搜索功能实现（搜索算法+数组降维）</h2> <p>将二维数组转为一维数组</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> arr <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token number">5</span><span class="token punctuation">]</span><span class="token punctuation">]</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">concat</span><span class="token punctuation">.</span><span class="token function">apply</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span> arr<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// [1, 2, 3, 4, 5]</span>
</code></pre></div><h2 id="全文搜索功能实现-搜索关键字高亮-搜索结果高亮显示"><a href="#全文搜索功能实现-搜索关键字高亮-搜索结果高亮显示" class="header-anchor">#</a> 全文搜索功能实现 （搜索关键字高亮+搜索结果高亮显示）</h2> <div class="language-vue extra-class"><pre class="language-vue"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>slide-contents-search-input<span class="token punctuation">&quot;</span></span>
  <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>text<span class="token punctuation">&quot;</span></span>
  <span class="token attr-name">v-model</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>searchText<span class="token punctuation">&quot;</span></span>
  <span class="token attr-name">@keyup.enter.exact</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>search()<span class="token punctuation">&quot;</span></span>
<span class="token punctuation">&gt;</span></span>
</code></pre></div><p>搜索内容高亮</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token function">highlightedSearchContent</span> <span class="token punctuation">(</span><span class="token parameter">target</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span>currentBook<span class="token punctuation">.</span>rendition<span class="token punctuation">.</span>annotations<span class="token punctuation">.</span><span class="token function">highlight</span><span class="token punctuation">(</span>target<span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre></div><p>搜索结果高亮</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token function">highlightedSearchContent</span> <span class="token punctuation">(</span><span class="token parameter">list</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span>searchList <span class="token operator">=</span> list
  <span class="token keyword">this</span><span class="token punctuation">.</span>searchList<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token parameter">item</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    item<span class="token punctuation">.</span>excerpt <span class="token operator">=</span> item<span class="token punctuation">.</span>excerpt<span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>searchText<span class="token punctuation">,</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">&lt;span class=&quot;content-search-text&quot;&gt;</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token keyword">this</span><span class="token punctuation">.</span>searchText<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">&lt;/span&gt;</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span>
    <span class="token keyword">return</span> item
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token function">search</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> searchText <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>searchText<span class="token punctuation">.</span><span class="token function">trim</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>searchText<span class="token punctuation">)</span> <span class="token keyword">return</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">doSearch</span><span class="token punctuation">(</span>searchText<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>highlightedSearchContent<span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
</code></pre></div><h2 id="书签手势实现-页面下拉"><a href="#书签手势实现-页面下拉" class="header-anchor">#</a> 书签手势实现（页面下拉）</h2> <p>用手指按下屏幕并向下拖动阅读器右上角会出现白色书签的标识和下拉添加书签的提示，继续向下拖动，到达一定阈值后文字内容会变为松手添加书签，书签的颜色会变成蓝色，此时松手书签就添加成功了，蓝色的书签会固定在界面上。在书签页面向下滑动到一定阈值松手后会删除书签。</p> <p>第一部分是在阅读器中添加手势或者鼠标的移动事件，通过监听touchmove事件获取移动的高度，当监听到这个事件后需要对最外层进行向下移动，改变页面的top值</p> <p>首先我们尝试给阅读器添加touchmove事件，然后在阅读器页面向下滑动，但是并没有触发touchmove事件，这是因为阅读器并没有提供touchmove事件。</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">this</span><span class="token punctuation">.</span>reader<span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">'touchmove'</span><span class="token punctuation">,</span> <span class="token parameter">e</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'touchmove'</span><span class="token punctuation">,</span> e<span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><p>我们需要使用蒙层的方式来给阅读器添加事件</p> <div class="language-vue extra-class"><pre class="language-vue"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>template</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>ebook-reader<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>ebook-reader-mask<span class="token punctuation">&quot;</span></span>
         <span class="token attr-name">@touchmove</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>move<span class="token punctuation">&quot;</span></span>
         <span class="token attr-name">@touchend</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>moveEnd<span class="token punctuation">&quot;</span></span>
         <span class="token attr-name">@mousedown.left</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>onMouseEnter<span class="token punctuation">&quot;</span></span>
         <span class="token attr-name">@mousemove.left</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>onMouseMove<span class="token punctuation">&quot;</span></span>
         <span class="token attr-name">@mouseup.left</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>onMouseEnd<span class="token punctuation">&quot;</span></span> <span class="token attr-name">@click</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>onMaskClick<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>read-wrapper<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>reader<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>template</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><h2 id="书签手势实现-书签组件"><a href="#书签手势实现-书签组件" class="header-anchor">#</a> 书签手势实现（书签组件）</h2> <p>css实现书签</p> <div class="language-css extra-class"><pre class="language-css"><code><span class="token selector">.ebook-bookmark-icon</span> <span class="token punctuation">{</span>
  <span class="token property">width</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span>
  <span class="token property">height</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span>
  <span class="token property">font-weight</span><span class="token punctuation">:</span> bold<span class="token punctuation">;</span>
  <span class="token property">line-height</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span>
  <span class="token property">border-width</span><span class="token punctuation">:</span> <span class="token function">px2rem</span><span class="token punctuation">(</span>50<span class="token punctuation">)</span> <span class="token function">px2rem</span><span class="token punctuation">(</span>10<span class="token punctuation">)</span> <span class="token function">px2rem</span><span class="token punctuation">(</span>10<span class="token punctuation">)</span> <span class="token function">px2rem</span><span class="token punctuation">(</span>10<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">border-style</span><span class="token punctuation">:</span> solid<span class="token punctuation">;</span>
  <span class="token property">border-color</span><span class="token punctuation">:</span> white white transparent white<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><h2 id="书签手势实现-下拉状态管理"><a href="#书签手势实现-下拉状态管理" class="header-anchor">#</a> 书签手势实现（下拉状态管理）</h2> <p>第一阶段书签随着屏幕向下拖动而拖动
第二个阶段书签吸顶阶段
第三个阶段书签满足添加添加条件</p> <p>书签初步吸顶效果，原理是书签做相对位移</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">this</span><span class="token punctuation">.</span>$refs<span class="token punctuation">.</span>ebookBookmark<span class="token punctuation">.</span>style<span class="token punctuation">.</span>top <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token operator">-</span>v<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">px</span><span class="token template-punctuation string">`</span></span>
</code></pre></div><h2 id="书签手势实现-书签添加删除交互"><a href="#书签手势实现-书签添加删除交互" class="header-anchor">#</a> 书签手势实现（书签添加删除交互）</h2> <p>书签箭头的交互</p> <div class="language-js extra-class"><pre class="language-js"><code>watch<span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token function">offsetY</span> <span class="token punctuation">(</span><span class="token parameter">v</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>v <span class="token operator">&gt;=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>height <span class="token operator">&amp;&amp;</span> v <span class="token operator">&lt;=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>threshold<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 第二阶段</span>
    <span class="token comment">// ...</span>
    <span class="token keyword">const</span> iconDown <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>$refs<span class="token punctuation">.</span>iconDown
    <span class="token keyword">if</span> <span class="token punctuation">(</span>iconDown<span class="token punctuation">.</span>style<span class="token punctuation">.</span>transform <span class="token operator">===</span> <span class="token string">'rotate(180deg)'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      iconDown<span class="token punctuation">.</span>style<span class="token punctuation">.</span>transform <span class="token operator">=</span> <span class="token string">'rotate(0deg)'</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>v <span class="token operator">&gt;=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>threshold<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 第三阶段</span>
    <span class="token comment">// ...</span>
    <span class="token keyword">const</span> iconDown <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>$refs<span class="token punctuation">.</span>iconDown
    <span class="token keyword">if</span> <span class="token punctuation">(</span>iconDown<span class="token punctuation">.</span>style<span class="token punctuation">.</span>transform <span class="token operator">===</span> <span class="token string">''</span> <span class="token operator">||</span> iconDown<span class="token punctuation">.</span>style<span class="token punctuation">.</span>transform <span class="token operator">===</span> <span class="token string">'rotate(0deg)'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      iconDown<span class="token punctuation">.</span>style<span class="token punctuation">.</span>transform <span class="token operator">=</span> <span class="token string">'rotate(180deg)'</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><h2 id="epubcfi原理介绍"><a href="#epubcfi原理介绍" class="header-anchor">#</a> EpubCFI原理介绍</h2> <p>epubcfi(/6/28[A370011_1_En_6_Chapter]!/4/8/10[Sec5]/6[Par21]/5:76)
epubcfi(/6/28[A370011_1_En_6_Chapter]!/4/8/10[Sec5]/8[Par22]/5:183)
<img src="/assets/img/5.0669f26a.png" alt=""> <img src="/assets/img/6.ae9eabb4.png" alt=""> <img src="/assets/img/7.5c67c8ab.png" alt=""></p> <h2 id="书签功能实现"><a href="#书签功能实现" class="header-anchor">#</a> 书签功能实现</h2> <p>添加书签</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token function">addBookmark</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span>bookmark <span class="token operator">=</span> <span class="token function">getBookmark</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>fileName<span class="token punctuation">)</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token keyword">this</span><span class="token punctuation">.</span>bookmark<span class="token punctuation">)</span> <span class="token keyword">this</span><span class="token punctuation">.</span>bookmark <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>

  <span class="token keyword">const</span> cur <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>currentBook<span class="token punctuation">.</span>rendition<span class="token punctuation">.</span><span class="token function">currentLocation</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'curcur'</span><span class="token punctuation">,</span> cur<span class="token punctuation">)</span>
  <span class="token comment">// start.cfi = 'epubcfi(/6/28[A370011_1_En_6_Chapter]!/4/8/10[Sec5]/6[Par21]/5:76)'</span>
  <span class="token comment">// end.cfi = 'epubcfi(/6/28[A370011_1_En_6_Chapter]!/4/8/10[Sec5]/8[Par22]/5:183)'</span>
  <span class="token comment">// 取出cfi叹号前面的部分</span>
  <span class="token keyword">const</span> cfibase <span class="token operator">=</span> cur<span class="token punctuation">.</span>start<span class="token punctuation">.</span>cfi<span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">!.*</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">)</span>
  <span class="token comment">// 取出cfi后面的部分</span>
  <span class="token keyword">const</span> cfistart <span class="token operator">=</span> cur<span class="token punctuation">.</span>start<span class="token punctuation">.</span>cfi<span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">.*!</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\)$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">)</span>
  <span class="token keyword">const</span> cfiend <span class="token operator">=</span> cur<span class="token punctuation">.</span>end<span class="token punctuation">.</span>cfi<span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">.*!</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\)$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">)</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'cfibase'</span><span class="token punctuation">,</span> cfibase<span class="token punctuation">)</span> <span class="token comment">// epubcfi(/6/28[A370011_1_En_6_Chapter]</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'cfistart'</span><span class="token punctuation">,</span> cfistart<span class="token punctuation">)</span> <span class="token comment">// /4/8/10[Sec5]/6[Par21]/5:76</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'cfiend'</span><span class="token punctuation">,</span> cfiend<span class="token punctuation">)</span> <span class="token comment">// /4/8/10[Sec5]/8[Par22]/5:183</span>
  <span class="token keyword">const</span> cfirange <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>cfibase<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">!,</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>cfistart<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">,</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>cfiend<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">)</span><span class="token template-punctuation string">`</span></span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'cfirange'</span><span class="token punctuation">,</span> cfirange<span class="token punctuation">)</span> <span class="token comment">// epubcfi(/6/28[A370011_1_En_6_Chapter]!/4/8/10[Sec5]/6[Par21]/5:76,/4/8/10[Sec5]/8[Par22]/5:183)</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span>currentBook<span class="token punctuation">.</span><span class="token function">getRange</span><span class="token punctuation">(</span>cfirange<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">range</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'range'</span><span class="token punctuation">,</span> range<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token keyword">const</span> text <span class="token operator">=</span> range<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\$\$</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">)</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'text'</span><span class="token punctuation">,</span> text<span class="token punctuation">)</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>bookmark<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
      <span class="token comment">// 用于判断当前页是不是书签页</span>
      cif<span class="token operator">:</span> cur<span class="token punctuation">.</span>start<span class="token punctuation">.</span>cfi<span class="token punctuation">,</span>
      <span class="token comment">// 用于显示文本</span>
      text
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
    <span class="token function">saveBookmark</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>fileName<span class="token punctuation">,</span> <span class="token keyword">this</span><span class="token punctuation">.</span>bookmark<span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre></div><p>删除书签</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token function">removeBookmark</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span>bookmark <span class="token operator">=</span> <span class="token function">getBookmark</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>fileName<span class="token punctuation">)</span>
  <span class="token keyword">const</span> cur <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>currentBook<span class="token punctuation">.</span>rendition<span class="token punctuation">.</span><span class="token function">currentLocation</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token keyword">const</span> startcfi <span class="token operator">=</span> cur<span class="token punctuation">.</span>start<span class="token punctuation">.</span>cfi
  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>bookmark<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token function">saveBookmark</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>fileName<span class="token punctuation">,</span> <span class="token keyword">this</span><span class="token punctuation">.</span>bookmark<span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token parameter">item</span> <span class="token operator">=&gt;</span> item <span class="token operator">!==</span> startcfi<span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setBookmark</span><span class="token punctuation">(</span><span class="token boolean">false</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><p>判断当前页是否显示书签</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token function">watch</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token function">isBookmark</span> <span class="token punctuation">(</span><span class="token parameter">isBookmark</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>isFixed <span class="token operator">=</span> isBookmark
    <span class="token keyword">this</span><span class="token punctuation">.</span>color <span class="token operator">=</span> isBookmark <span class="token operator">?</span> <span class="token constant">BLUE</span> <span class="token operator">:</span> <span class="token constant">WHITE</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token comment">// mixin.js</span>
<span class="token function">refreshContent</span> <span class="token punctuation">(</span><span class="token parameter">d</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token comment">// 省略若干代码</span>
  <span class="token comment">// 渲染当前页时判断当前页是否显示书签</span>
  <span class="token keyword">const</span> bookmark <span class="token operator">=</span> <span class="token function">getBookmark</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>fileName<span class="token punctuation">)</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>bookmark<span class="token punctuation">)</span>
  bookmark <span class="token operator">&amp;&amp;</span> bookmark<span class="token punctuation">.</span><span class="token function">some</span><span class="token punctuation">(</span><span class="token parameter">item</span> <span class="token operator">=&gt;</span> item<span class="token punctuation">.</span>cfi <span class="token operator">===</span> cfi<span class="token punctuation">)</span> <span class="token operator">?</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setIsBookmark</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setIsBookmark</span><span class="token punctuation">(</span><span class="token boolean">false</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre></div><h2 id="阅读模式介绍"><a href="#阅读模式介绍" class="header-anchor">#</a> 阅读模式介绍</h2> <p>在initRender方法中传入<code>flow: 'scrolled'</code>就可在阅读器中通过上下滚动来阅读电子书了，但是这种模式目前微信和苹果手机都还不支持，所以不建议使用。</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token function">initRender</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span>reader <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>book<span class="token punctuation">.</span><span class="token function">renderTo</span><span class="token punctuation">(</span><span class="token string">'reader'</span><span class="token punctuation">,</span> <span class="token punctuation">{</span>
    width<span class="token operator">:</span> innerWidth<span class="token punctuation">,</span>
    height<span class="token operator">:</span> innerHeight<span class="token punctuation">,</span>
    flow<span class="token operator">:</span> <span class="token string">'scrolled'</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token comment">// ...</span>
<span class="token punctuation">}</span>
</code></pre></div><h2 id="微信兼容性调整"><a href="#微信兼容性调整" class="header-anchor">#</a> 微信兼容性调整</h2> <div class="language-scss extra-class"><pre class="language-scss"><code><span class="token selector">html, body </span><span class="token punctuation">{</span>
  <span class="token property">width</span><span class="token punctuation">:</span> 100%<span class="token punctuation">;</span>
  <span class="token property">height</span><span class="token punctuation">:</span> 100%<span class="token punctuation">;</span>
  <span class="token property">user-select</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span>
  <span class="token property">overflow</span><span class="token punctuation">:</span> hidden<span class="token punctuation">;</span>
  <span class="token property">font-family</span><span class="token punctuation">:</span> <span class="token string">'Segoe UI'</span><span class="token punctuation">,</span> Tahoma<span class="token punctuation">,</span> Geneva<span class="token punctuation">,</span> Verdana<span class="token punctuation">,</span> sans-serif<span class="token punctuation">;</span>
  <span class="token comment">// 修复微信端翻页页面闪烁的问题</span>
  <span class="token property">-webkit-tap-highlight-color</span><span class="token punctuation">:</span> <span class="token function">rgba</span><span class="token punctuation">(</span>0<span class="token punctuation">,</span> 0<span class="token punctuation">,</span> 0<span class="token punctuation">,</span> 0<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><h2 id="书签支持鼠标事件"><a href="#书签支持鼠标事件" class="header-anchor">#</a> 书签支持鼠标事件</h2> <div class="language-js extra-class"><pre class="language-js"><code><span class="token function">onMouseEnter</span> <span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span>mouseState <span class="token operator">=</span> <span class="token number">1</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span>mouseStartTime <span class="token operator">=</span> e<span class="token punctuation">.</span>timeStamp
  e<span class="token punctuation">.</span><span class="token function">preventDefault</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  e<span class="token punctuation">.</span><span class="token function">stopPropagation</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token function">onMouseMove</span> <span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>mouseState <span class="token operator">===</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>mouseState <span class="token operator">=</span> <span class="token number">2</span>
  <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>mouseState <span class="token operator">===</span> <span class="token number">2</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>menuVisible <span class="token operator">||</span> <span class="token operator">!</span><span class="token keyword">this</span><span class="token punctuation">.</span>bookAvailable<span class="token punctuation">)</span> <span class="token keyword">return</span>

    <span class="token keyword">this</span><span class="token punctuation">.</span>firstOffsetY <span class="token operator">?</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setOffsetY</span><span class="token punctuation">(</span>e<span class="token punctuation">.</span>clientY <span class="token operator">-</span> <span class="token keyword">this</span><span class="token punctuation">.</span>firstOffsetY<span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token keyword">this</span><span class="token punctuation">.</span>firstOffsetY <span class="token operator">=</span> e<span class="token punctuation">.</span>clientY
  <span class="token punctuation">}</span>
  e<span class="token punctuation">.</span><span class="token function">preventDefault</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  e<span class="token punctuation">.</span><span class="token function">stopPropagation</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token function">onMouseEnd</span> <span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>mouseState <span class="token operator">===</span> <span class="token number">2</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setOffsetY</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>firstOffsetY <span class="token operator">=</span> <span class="token keyword">null</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>mouseState <span class="token operator">=</span> <span class="token number">3</span>
  <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>mouseState <span class="token operator">=</span> <span class="token number">4</span>
  <span class="token punctuation">}</span>
  <span class="token keyword">const</span> time <span class="token operator">=</span> e<span class="token punctuation">.</span>timeStamp <span class="token operator">-</span> <span class="token keyword">this</span><span class="token punctuation">.</span>mouseStartTime
  <span class="token keyword">if</span> <span class="token punctuation">(</span>time <span class="token operator">&lt;</span> <span class="token number">300</span><span class="token punctuation">)</span> <span class="token keyword">this</span><span class="token punctuation">.</span>mouseState <span class="token operator">=</span> <span class="token number">4</span>
  e<span class="token punctuation">.</span><span class="token function">preventDefault</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  e<span class="token punctuation">.</span><span class="token function">stopPropagation</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre></div><h2 id="阅读器分页算法实现"><a href="#阅读器分页算法实现" class="header-anchor">#</a> 阅读器分页算法实现</h2> <div class="language-js extra-class"><pre class="language-js"><code><span class="token function">initPaging</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span>book<span class="token punctuation">.</span>ready<span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>book<span class="token punctuation">.</span>locations<span class="token punctuation">.</span><span class="token function">generate</span><span class="token punctuation">(</span><span class="token number">750</span> <span class="token operator">*</span> <span class="token punctuation">(</span>window<span class="token punctuation">.</span>innerWidth <span class="token operator">/</span> <span class="token number">375</span><span class="token punctuation">)</span> <span class="token operator">*</span> <span class="token punctuation">(</span><span class="token function">getFontSize</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>fileName<span class="token punctuation">)</span> <span class="token operator">/</span> <span class="token number">16</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">locations</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token comment">// console.log(locations)</span>

    <span class="token keyword">this</span><span class="token punctuation">.</span>navigation<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token parameter">nav</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
      nav<span class="token punctuation">.</span>pageList <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>

    locations<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token parameter">item</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
      <span class="token keyword">const</span> l <span class="token operator">=</span> item<span class="token punctuation">.</span><span class="token function">match</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\[(.*)\]!</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span>
      <span class="token keyword">this</span><span class="token punctuation">.</span>navigation<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token parameter">nav</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>nav<span class="token punctuation">.</span>href<span class="token punctuation">)</span> <span class="token punctuation">{</span>
          <span class="token keyword">const</span> href <span class="token operator">=</span> nav<span class="token punctuation">.</span>href<span class="token punctuation">.</span><span class="token function">match</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">^(.*)\.html$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span>
          <span class="token keyword">if</span> <span class="token punctuation">(</span>href <span class="token operator">===</span> l<span class="token punctuation">)</span> <span class="token punctuation">{</span>
            nav<span class="token punctuation">.</span>pageList<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>item<span class="token punctuation">)</span>
          <span class="token punctuation">}</span>
        <span class="token punctuation">}</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span>
      <span class="token keyword">let</span> curPage <span class="token operator">=</span> <span class="token number">1</span>
      <span class="token keyword">this</span><span class="token punctuation">.</span>navigation<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">nav<span class="token punctuation">,</span> index</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>index <span class="token operator">===</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
          nav<span class="token punctuation">.</span>page <span class="token operator">=</span> <span class="token number">1</span>
        <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
          nav<span class="token punctuation">.</span>page <span class="token operator">=</span> curPage
        <span class="token punctuation">}</span>
        curPage <span class="token operator">+=</span> nav<span class="token punctuation">.</span>pageList<span class="token punctuation">.</span>length <span class="token operator">+</span> <span class="token number">1</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>

    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setBookAvailable</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span>
    <span class="token comment">// 分页完成后</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">refreshContent</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre></div><h2 id="书城首页开发-框架页面-路由配置"><a href="#书城首页开发-框架页面-路由配置" class="header-anchor">#</a> 书城首页开发（框架页面+路由配置）</h2> <h2 id="书城首页-标题-搜索框布局"><a href="#书城首页-标题-搜索框布局" class="header-anchor">#</a> 书城首页（标题+搜索框布局）</h2> <div class="language-css extra-class"><pre class="language-css"><code><span class="token selector">.search-bar-input</span> <span class="token punctuation">{</span>
  <span class="token property">width</span><span class="token punctuation">:</span> 100%<span class="token punctuation">;</span>
  <span class="token property">border-radius</span><span class="token punctuation">:</span> <span class="token function">px2rem</span><span class="token punctuation">(</span>20<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">background-color</span><span class="token punctuation">:</span> #f4f4f4<span class="token punctuation">;</span>
  <span class="token property">padding</span><span class="token punctuation">:</span> <span class="token function">px2rem</span><span class="token punctuation">(</span>5<span class="token punctuation">)</span> <span class="token function">px2rem</span><span class="token punctuation">(</span>15<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">box-sizing</span><span class="token punctuation">:</span> border-box<span class="token punctuation">;</span>
  <span class="token property">border</span><span class="token punctuation">:</span> <span class="token function">px2rem</span><span class="token punctuation">(</span>1<span class="token punctuation">)</span> solid #eee<span class="token punctuation">;</span>
  <span class="token atrule"><span class="token rule">@include</span> left<span class="token punctuation">;</span></span>
  <span class="token selector">.icon-search</span> <span class="token punctuation">{</span>
    <span class="token property">color</span><span class="token punctuation">:</span> #999<span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token selector">.input</span> <span class="token punctuation">{</span>
    <span class="token property">width</span><span class="token punctuation">:</span> 100%<span class="token punctuation">;</span>
    <span class="token property">height</span><span class="token punctuation">:</span> <span class="token function">px2rem</span><span class="token punctuation">(</span>22<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token property">border</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span>
    <span class="token property">margin-left</span><span class="token punctuation">:</span> <span class="token function">px2rem</span><span class="token punctuation">(</span>10<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token property">font-size</span><span class="token punctuation">:</span> <span class="token function">px2rem</span><span class="token punctuation">(</span>12<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token property">color</span><span class="token punctuation">:</span> #666<span class="token punctuation">;</span>
    <span class="token property">background-color</span><span class="token punctuation">:</span> transparent<span class="token selector">;
    &amp;:focus</span> <span class="token punctuation">{</span>
      <span class="token property">outline</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token selector">&amp;::-webkit-input-placeholder</span> <span class="token punctuation">{</span>
      <span class="token property">color</span><span class="token punctuation">:</span> #ccc<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><h2 id="书城首页-标题-搜索框交互设计分析"><a href="#书城首页-标题-搜索框交互设计分析" class="header-anchor">#</a> 书城首页（标题+搜索框交互设计分析）</h2> <p>标题和推荐图标向下渐隐</p> <p>搜索框向上移动到标题位置</p> <p>搜索框逐渐变窄以适应屏幕</p> <p>返回按钮向下居中</p> <p>标题下方显示阴影</p> <h2 id="书城首页-标题交互动画实现"><a href="#书城首页-标题交互动画实现" class="header-anchor">#</a> 书城首页（标题交互动画实现）</h2> <h2 id="书城首页-搜索框交互动画实现"><a href="#书城首页-搜索框交互动画实现" class="header-anchor">#</a> 书城首页（搜索框交互动画实现</h2> <h2 id="书城首页-热门搜索布局"><a href="#书城首页-热门搜索布局" class="header-anchor">#</a> 书城首页（热门搜索布局）</h2> <h2 id="书城首页-热门搜索交互"><a href="#书城首页-热门搜索交互" class="header-anchor">#</a> 书城首页（热门搜索交互）</h2> <h2 id="书城首页-推荐页面布局"><a href="#书城首页-推荐页面布局" class="header-anchor">#</a> 书城首页（推荐页面布局）</h2> <p>推荐的交互细节分析</p> <p>1.弹出卡片
2.卡片翻转动画
3.烟花动画
4.弹出推荐图书</p> <p>推荐弹窗关闭按钮的样式实现</p> <div class="language-vue extra-class"><pre class="language-vue"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>close-btn-wrapper<span class="token punctuation">&quot;</span></span> <span class="token attr-name">@click</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>handleClick<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>icon-close<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><div class="language-css extra-class"><pre class="language-css"><code><span class="token selector">.close-btn-wrapper</span> <span class="token punctuation">{</span>
  <span class="token property">position</span><span class="token punctuation">:</span> absolute<span class="token punctuation">;</span>
  <span class="token property">left</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span>
  <span class="token property">bottom</span><span class="token punctuation">:</span> <span class="token function">px2rem</span><span class="token punctuation">(</span>30<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token property">z-index</span><span class="token punctuation">:</span> 999<span class="token punctuation">;</span>
  <span class="token property">width</span><span class="token punctuation">:</span> 100%<span class="token punctuation">;</span>
  <span class="token atrule"><span class="token rule">@include</span> center<span class="token punctuation">;</span></span>
  <span class="token selector">.icon-close</span> <span class="token punctuation">{</span>
    <span class="token property">width</span><span class="token punctuation">:</span> <span class="token function">px2rem</span><span class="token punctuation">(</span>45<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token property">height</span><span class="token punctuation">:</span> <span class="token function">px2rem</span><span class="token punctuation">(</span>45<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token property">font-size</span><span class="token punctuation">:</span> <span class="token function">px2rem</span><span class="token punctuation">(</span>25<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token property">border-radius</span><span class="token punctuation">:</span> 50%<span class="token punctuation">;</span>
    <span class="token property">background-color</span><span class="token punctuation">:</span> #333<span class="token punctuation">;</span>
    <span class="token property">color</span><span class="token punctuation">:</span> #fff<span class="token punctuation">;</span>
    <span class="token atrule"><span class="token rule">@include</span> center<span class="token punctuation">;</span></span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><h2 id="书城首页-卡片翻转动画实现"><a href="#书城首页-卡片翻转动画实现" class="header-anchor">#</a> 书城首页（卡片翻转动画实现）</h2> <div class="language-css extra-class"><pre class="language-css"><code><span class="token property">transform-origin</span><span class="token punctuation">:</span> left<span class="token punctuation">;</span>
</code></pre></div><div class="language-css extra-class"><pre class="language-css"><code><span class="token property">backface-visibility</span><span class="token punctuation">:</span> hidden<span class="token punctuation">;</span>
</code></pre></div><h2 id="书城首页-卡片翻转动画重置"><a href="#书城首页-卡片翻转动画重置" class="header-anchor">#</a> 书城首页（卡片翻转动画重置）</h2> <h2 id="书城首页-卡片登场keyframes动画讲解"><a href="#书城首页-卡片登场keyframes动画讲解" class="header-anchor">#</a> 书城首页（卡片登场keyframes动画讲解）</h2> <h2 id="书城首页-烟花动画实现"><a href="#书城首页-烟花动画实现" class="header-anchor">#</a> 书城首页（烟花动画实现）</h2> <h2 id="书城首页-mockjs使用方法讲解"><a href="#书城首页-mockjs使用方法讲解" class="header-anchor">#</a> 书城首页（mockjs使用方法讲解）</h2> <p>mock.js原理替换原生的XMLHttpRequest，使用方便</p> <p>mock.js提供了非常丰富的数据类型</p> <p>但无法支持blob类型，无法模拟下载</p> <p>安装时注意mock.js和mockjs不是一个东西</p> <div class="language-sh extra-class"><pre class="language-sh"><code><span class="token function">npm</span> i mockjs -D
</code></pre></div><div class="language- extra-class"><pre class="language-text"><code>Mock.mock( rurl, rtype, template )
</code></pre></div><p>记录数据模板。当拦截到匹配 rurl 和 rtype 的 Ajax 请求时，将根据数据模板 template 生成模拟数据，并作为响应数据返回。</p> <p>第二个参数必须小写，大写不行</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">import</span> Mock <span class="token keyword">from</span> <span class="token string">'mockjs'</span>
<span class="token keyword">import</span> BookHomeApi <span class="token keyword">from</span> <span class="token string">'./bookHome'</span>
<span class="token comment">/*
第一个参数：匹配请求的url
第二个参数：请求方法
第三个参数：数据模板
*/</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Mock'</span><span class="token punctuation">,</span> Mock<span class="token punctuation">)</span>
Mock<span class="token punctuation">.</span><span class="token function">mock</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\/book\/home</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span> <span class="token string">'get'</span><span class="token punctuation">,</span> BookHomeApi<span class="token punctuation">)</span>
<span class="token keyword">export</span> <span class="token keyword">default</span> Mock
</code></pre></div><p>会报错
<img src="/assets/img/8.e1bdefd7.png" alt=""></p> <h2 id="书城首页-推荐图书布局-动画"><a href="#书城首页-推荐图书布局-动画" class="header-anchor">#</a> 书城首页（推荐图书布局+动画）</h2> <h2 id="书城首页-首页图书布局实现"><a href="#书城首页-首页图书布局实现" class="header-anchor">#</a> 书城首页（首页图书布局实现）</h2> <h2 id="书城详情页开发"><a href="#书城详情页开发" class="header-anchor">#</a> 书城详情页开发</h2> <p>我们下载电子书的时候下载下来的是一个blob对象，epub.js会解析这个blob对象并且进行电子书的展示，但是mockjs不支持blob对象，它只支持text文本进行展示，所以下载电子书的时候就会出现错误</p> <p>下载类、资源类的接口不能使用mockjs。</p> <p>我们可以使用第二种方式进行mock</p> <p>vue.config.js</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">mock</span><span class="token punctuation">(</span><span class="token parameter">app<span class="token punctuation">,</span> url<span class="token punctuation">,</span> data</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  app<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>url<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">request<span class="token punctuation">,</span> response</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    response<span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span>data<span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token keyword">const</span> homeData <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'./src/mock/bookHome'</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> shelfData <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'./src/mock/bookShelf'</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> listData <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'./src/mock/bookList'</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> flatListData <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'./src/mock/bookFlatList'</span><span class="token punctuation">)</span>

<span class="token keyword">function</span> <span class="token function">mock</span><span class="token punctuation">(</span><span class="token parameter">app<span class="token punctuation">,</span> url<span class="token punctuation">,</span> data</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  app<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>url<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">request<span class="token punctuation">,</span> response</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    response<span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span>data<span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token keyword">const</span> homeData <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'./src/mock/bookHome'</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> shelfData <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'./src/mock/bookShelf'</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> listData <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'./src/mock/bookList'</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> flatListData <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'./src/mock/bookFlatList'</span><span class="token punctuation">)</span>
</code></pre></div><h2 id="书城列表页开发"><a href="#书城列表页开发" class="header-anchor">#</a> 书城列表页开发</h2> <h2 id="第七章总结"><a href="#第七章总结" class="header-anchor">#</a> 第七章总结</h2> <h2 id="书架"><a href="#书架" class="header-anchor">#</a> 书架</h2> <div class="language- extra-class"><pre class="language-text"><code>* core-js/modules/es6.array.find in ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/ebook/EbookSlideContent.vue?vue&amp;type=script&amp;lang=js&amp;, ./src/utils/book.js
* core-js/modules/es6.array.find-index in ./src/utils/book.js
* core-js/modules/es6.function.name in ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/ebook/EbookReader.vue?vue&amp;type=script&amp;lang=js&amp;, ./src/utils/mixin.js
* core-js/modules/es6.number.constructor in ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/Scroll.vue?vue&amp;type=script&amp;lang=js&amp;, ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/ebook/Bookmark.vue?vue&amp;type=script&amp;lang=js&amp; and 5 others
* core-js/modules/es6.number.max-safe-integer in ./src/utils/book.js, ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/store/bookShelf.vue?vue&amp;type=script&amp;lang=js&amp;
* core-js/modules/es6.object.keys in ./src/utils/mixin.js, ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/store/bookList.vue?vue&amp;type=script&amp;lang=js&amp;
* core-js/modules/es6.regexp.constructor in ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/store/bookDetail.vue?vue&amp;type=script&amp;lang=js&amp;
* core-js/modules/es6.regexp.match in ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/ebook/EbookReader.vue?vue&amp;type=script&amp;lang=js&amp;
* core-js/modules/es6.regexp.replace in ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/ebook/EbookBookmark.vue?vue&amp;type=script&amp;lang=js&amp;, ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/home/guessYouLike.vue?vue&amp;type=script&amp;lang=js&amp; and 4 others
* core-js/modules/es6.regexp.split in ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/ebook/EbookReader.vue?vue&amp;type=script&amp;lang=js&amp;
* core-js/modules/es6.regexp.to-string in ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/ebook/EbookBookmark.vue?vue&amp;type=script&amp;lang=js&amp;, ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/speak/speakMask.vue?vue&amp;type=script&amp;lang=js&amp;
* core-js/modules/es6.string.fixed in ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/ebook/EbookBookmark.vue?vue&amp;type=script&amp;lang=js&amp;
* core-js/modules/es6.string.iterator in ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/ebook/EbookReader.vue?vue&amp;type=script&amp;lang=js&amp;
* core-js/modules/es6.string.starts-with in ./src/utils/mixin.js, ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/store/bookDetail.vue?vue&amp;type=script&amp;lang=js&amp;
* core-js/modules/es7.object.get-own-property-descriptors in ./src/utils/mixin.js
* core-js/modules/web.dom.iterable in ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/ebook/EbookReader.vue?vue&amp;type=script&amp;lang=js&amp;, ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/home/guessYouLike.vue?vue&amp;type=script&amp;lang=js&amp; and 4 others

To install them, you can run: npm install --save core-js/modules/es6.array.find core-js/modules/es6.array.find-index core-js/modules/es6.function.name core-js/modules/es6.number.constructor core-js/modules/es6.number.max-safe-integer core-js/modules/es6.object.keys core-js/modules/es6.regexp.constructor core-js/modules/es6.regexp.match core-js/modules/es6.regexp.replace core-js/modules/es6.regexp.split core-js/modules/es6.regexp.to-string core-js/modules/es6.string.fixed core-js/modules/es6.string.iterator core-js/modules/es6.string.starts-with core-js/modules/es7.object.get-own-property-descriptors core-js/modules/web.dom.iterable
</code></pre></div><p>解决办法</p> <div class="language- extra-class"><pre class="language-text"><code>cnpm install core-js@2 
</code></pre></div><h2 id="书架标题组件布局实现"><a href="#书架标题组件布局实现" class="header-anchor">#</a> 书架标题组件布局实现</h2> <h2 id="书架标题组件交互实现"><a href="#书架标题组件交互实现" class="header-anchor">#</a> 书架标题组件交互实现</h2> <h2 id="书架搜索框布局实现"><a href="#书架搜索框布局实现" class="header-anchor">#</a> 书架搜索框布局实现</h2> <h2 id="书架搜索框交互实现"><a href="#书架搜索框交互实现" class="header-anchor">#</a> 书架搜索框交互实现</h2> <h2 id="书架数据结构设计-数据获取"><a href="#书架数据结构设计-数据获取" class="header-anchor">#</a> 书架数据结构设计+数据获取</h2> <h2 id="书架标题-搜索框样式优化"><a href="#书架标题-搜索框样式优化" class="header-anchor">#</a> 书架标题+搜索框样式优化</h2> <h2 id="书架图书列表实现"><a href="#书架图书列表实现" class="header-anchor">#</a> 书架图书列表实现</h2> <h2 id="书架图书列表布局"><a href="#书架图书列表布局" class="header-anchor">#</a> 书架图书列表布局</h2> <p>书架中图书高度计算</p> <div class="language-js extra-class"><pre class="language-js"><code>computed<span class="token operator">:</span> <span class="token punctuation">{</span>
  <span class="token function">itemHeight</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token comment">// w / 250 = h / 350</span>
    <span class="token comment">// h = w / 250 * 350</span>
    <span class="token comment">// 图片实际尺寸为350px 250px</span>
    <span class="token comment">// realPx(120)是书籍与书籍之间的空白的间距</span>
    <span class="token keyword">return</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>window<span class="token punctuation">.</span>innerWidth <span class="token operator">-</span> <span class="token function">realPx</span><span class="token punctuation">(</span><span class="token number">120</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">/</span> <span class="token number">3</span><span class="token punctuation">)</span> <span class="token operator">/</span> <span class="token number">250</span> <span class="token operator">*</span> <span class="token number">350</span> <span class="token operator">+</span> <span class="token string">'px'</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><h2 id="书架图书组件开发-单书封面-分类书籍封面实现"><a href="#书架图书组件开发-单书封面-分类书籍封面实现" class="header-anchor">#</a> 书架图书组件开发(单书封面+分类书籍封面实现)</h2> <p>图书分组中九宫格布局padding的使用</p> <div class="language-scss extra-class"><pre class="language-scss"><code>&amp;<span class="token punctuation">:</span><span class="token function">nth-child</span><span class="token punctuation">(</span>3n+1<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token property">padding</span><span class="token punctuation">:</span> 0 <span class="token function">px2rem</span><span class="token punctuation">(</span>2.5<span class="token punctuation">)</span> <span class="token function">px2rem</span><span class="token punctuation">(</span>5<span class="token punctuation">)</span> <span class="token function">px2rem</span><span class="token punctuation">(</span>5<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
&amp;<span class="token punctuation">:</span><span class="token function">nth-child</span><span class="token punctuation">(</span>3n+2<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token property">padding</span><span class="token punctuation">:</span> 0 <span class="token function">px2rem</span><span class="token punctuation">(</span>2.5<span class="token punctuation">)</span> <span class="token function">px2rem</span><span class="token punctuation">(</span>5<span class="token punctuation">)</span> <span class="token function">px2rem</span><span class="token punctuation">(</span>2.5<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
&amp;<span class="token punctuation">:</span><span class="token function">nth-child</span><span class="token punctuation">(</span>3n+3<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token property">padding</span><span class="token punctuation">:</span> 0 <span class="token function">px2rem</span><span class="token punctuation">(</span>5<span class="token punctuation">)</span> <span class="token function">px2rem</span><span class="token punctuation">(</span>5<span class="token punctuation">)</span> <span class="token function">px2rem</span><span class="token punctuation">(</span>2.5<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">.shelf-item-category-img </span><span class="token punctuation">{</span>
  <span class="token property">width</span><span class="token punctuation">:</span> 100%<span class="token punctuation">;</span>
  <span class="token property">height</span><span class="token punctuation">:</span> 100%<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><h2 id="书架图书组件开发-添加-编辑实现"><a href="#书架图书组件开发-添加-编辑实现" class="header-anchor">#</a> 书架图书组件开发(添加+编辑实现)</h2> <h2 id="书架编辑模式开发"><a href="#书架编辑模式开发" class="header-anchor">#</a> 书架编辑模式开发</h2> <h2 id="书架弹出框组件开发"><a href="#书架弹出框组件开发" class="header-anchor">#</a> 书架弹出框组件开发</h2> <div class="language-sh extra-class"><pre class="language-sh"><code><span class="token function">npm</span> i vue-create-api -S
</code></pre></div><p>使用</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// src/utils/create-api.js</span>

<span class="token keyword">import</span> Vue <span class="token keyword">from</span> <span class="token string">'vue'</span>
<span class="token keyword">import</span> CreateAPI <span class="token keyword">from</span> <span class="token string">'vue-create-api'</span>
<span class="token keyword">import</span> Toast <span class="token keyword">from</span> <span class="token string">'../components/common/Toast'</span>

Vue<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>CreateAPI<span class="token punctuation">)</span>
Vue<span class="token punctuation">.</span><span class="token function">createAPI</span><span class="token punctuation">(</span>Toast<span class="token punctuation">,</span> <span class="token boolean">true</span><span class="token punctuation">)</span>

Vue<span class="token punctuation">.</span><span class="token function">mixin</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  methods<span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token function">toast</span><span class="token punctuation">(</span><span class="token parameter">settings</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">$createToast</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
        $props<span class="token operator">:</span> settings
      <span class="token punctuation">}</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token comment">// 组件内调用</span>
<span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">toast</span><span class="token punctuation">(</span><span class="token punctuation">{</span>text<span class="token operator">:</span> <span class="token string">'加载成功'</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">show</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</code></pre></div><p>src/components/common/Toast.vue</p> <div class="language-vue extra-class"><pre class="language-vue"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>template</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>transition</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>fade<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>toast-bg-wrapper<span class="token punctuation">&quot;</span></span> <span class="token attr-name">@click.prevent</span> <span class="token attr-name">v-show</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>visible<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
      <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>toast-bg<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>toast-wrapper<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
          <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>toast<span class="token punctuation">&quot;</span></span> <span class="token attr-name">v-html</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>showText<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
      <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>transition</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>template</span><span class="token punctuation">&gt;</span></span>

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script"><span class="token language-javascript">
<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token punctuation">{</span>
  name<span class="token operator">:</span> <span class="token string">'toast'</span><span class="token punctuation">,</span>
  props<span class="token operator">:</span> <span class="token punctuation">{</span>
    text<span class="token operator">:</span> <span class="token punctuation">[</span>String<span class="token punctuation">,</span> Number<span class="token punctuation">]</span><span class="token punctuation">,</span>
    timeout<span class="token operator">:</span> <span class="token punctuation">{</span>
      type<span class="token operator">:</span> Number<span class="token punctuation">,</span>
      <span class="token keyword">default</span><span class="token operator">:</span> <span class="token number">1500</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token function">data</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token punctuation">{</span>
      visible<span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span>
      showText<span class="token operator">:</span> <span class="token string">''</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  methods<span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token function">hide</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">this</span><span class="token punctuation">.</span>visible <span class="token operator">=</span> <span class="token boolean">false</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token function">show</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">updateText</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>text<span class="token punctuation">)</span>
      <span class="token function">clearTimeout</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>task<span class="token punctuation">)</span>
      <span class="token keyword">this</span><span class="token punctuation">.</span>task <span class="token operator">=</span> <span class="token keyword">null</span>
      <span class="token keyword">this</span><span class="token punctuation">.</span>visible <span class="token operator">=</span> <span class="token boolean">true</span>
      <span class="token keyword">this</span><span class="token punctuation">.</span>task <span class="token operator">=</span> <span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>visible <span class="token operator">=</span> <span class="token boolean">false</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token keyword">this</span><span class="token punctuation">.</span>timeout<span class="token punctuation">)</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token function">continueShow</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">updateText</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>text<span class="token punctuation">)</span>
      <span class="token function">clearTimeout</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>task<span class="token punctuation">)</span>
      <span class="token keyword">this</span><span class="token punctuation">.</span>task <span class="token operator">=</span> <span class="token keyword">null</span>
      <span class="token keyword">this</span><span class="token punctuation">.</span>visible <span class="token operator">=</span> <span class="token boolean">true</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token function">updateText</span> <span class="token punctuation">(</span><span class="token parameter">text</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">this</span><span class="token punctuation">.</span>showText <span class="token operator">=</span> text
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>style</span> <span class="token attr-name">lang</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>scss<span class="token punctuation">&quot;</span></span> <span class="token attr-name">rel</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>stylesheet/scss<span class="token punctuation">&quot;</span></span> <span class="token attr-name">scoped</span><span class="token punctuation">&gt;</span></span><span class="token style"><span class="token language-css">
  <span class="token atrule"><span class="token rule">@import</span> <span class="token string">&quot;../../assets/styles/global&quot;</span><span class="token punctuation">;</span></span>

  <span class="token selector">.toast-bg-wrapper</span> <span class="token punctuation">{</span>
    <span class="token property">position</span><span class="token punctuation">:</span> absolute<span class="token punctuation">;</span>
    <span class="token property">left</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span>
    <span class="token property">top</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span>
    <span class="token property">z-index</span><span class="token punctuation">:</span> 2500<span class="token punctuation">;</span>
    <span class="token property">width</span><span class="token punctuation">:</span> 100%<span class="token punctuation">;</span>
    <span class="token property">height</span><span class="token punctuation">:</span> 100%<span class="token punctuation">;</span>
    <span class="token property">background</span><span class="token punctuation">:</span> transparent<span class="token selector">;
    .toast-bg</span> <span class="token punctuation">{</span>
      <span class="token property">position</span><span class="token punctuation">:</span> absolute<span class="token punctuation">;</span>
      <span class="token property">top</span><span class="token punctuation">:</span> 50%<span class="token punctuation">;</span>
      <span class="token property">left</span><span class="token punctuation">:</span> 50%<span class="token punctuation">;</span>
      <span class="token property">margin</span><span class="token punctuation">:</span> 0 0 0 -50%<span class="token punctuation">;</span>
      <span class="token property">z-index</span><span class="token punctuation">:</span> 2500<span class="token punctuation">;</span>
      <span class="token property">width</span><span class="token punctuation">:</span> 100%<span class="token punctuation">;</span>
      <span class="token atrule"><span class="token rule">@include</span> center<span class="token punctuation">;</span></span>
      <span class="token selector">.toast-wrapper</span> <span class="token punctuation">{</span>
        <span class="token property">width</span><span class="token punctuation">:</span> 60%<span class="token punctuation">;</span>
        <span class="token property">line-height</span><span class="token punctuation">:</span> <span class="token function">px2rem</span><span class="token punctuation">(</span>20<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token property">padding</span><span class="token punctuation">:</span> <span class="token function">px2rem</span><span class="token punctuation">(</span>10<span class="token punctuation">)</span> <span class="token function">px2rem</span><span class="token punctuation">(</span>20<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token property">box-sizing</span><span class="token punctuation">:</span> border-box<span class="token punctuation">;</span>
        <span class="token property">background-color</span><span class="token punctuation">:</span> <span class="token function">rgba</span><span class="token punctuation">(</span>0<span class="token punctuation">,</span> 0<span class="token punctuation">,</span> 0<span class="token punctuation">,</span> 0.6<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token property">border-radius</span><span class="token punctuation">:</span> <span class="token function">px2rem</span><span class="token punctuation">(</span>10<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token property">font-size</span><span class="token punctuation">:</span> <span class="token function">px2rem</span><span class="token punctuation">(</span>14<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token property">color</span><span class="token punctuation">:</span> white<span class="token selector">;
        .toast</span> <span class="token punctuation">{</span>
          <span class="token property">text-align</span><span class="token punctuation">:</span> center<span class="token punctuation">;</span>
          <span class="token property">word-break</span><span class="token punctuation">:</span> break-all<span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>style</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><h2 id="书架弹出框功能开发"><a href="#书架弹出框功能开发" class="header-anchor">#</a> 书架弹出框功能开发</h2> <h2 id="书架弹出框功能开发-2"><a href="#书架弹出框功能开发-2" class="header-anchor">#</a> 书架弹出框功能开发</h2> <p>移除书架</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token function">removeSelected</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span>shelfSelected<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token parameter">selected</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setShelfList</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>shelfList<span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token parameter">book</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
      <span class="token keyword">if</span> <span class="token punctuation">(</span>book<span class="token punctuation">.</span>itemList<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        book<span class="token punctuation">.</span>itemList <span class="token operator">=</span> book<span class="token punctuation">.</span>itemList<span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token parameter">subItem</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
          <span class="token keyword">return</span> subItem <span class="token operator">!==</span> selected
        <span class="token punctuation">}</span><span class="token punctuation">)</span>
      <span class="token punctuation">}</span>
      <span class="token keyword">return</span> book <span class="token operator">!==</span> selected
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setShelfSelected</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">onComplete</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
</code></pre></div><h2 id="电子书离线缓存功能开发"><a href="#电子书离线缓存功能开发" class="header-anchor">#</a> 电子书离线缓存功能开发</h2> <p>localStorage 能够让你实现基本的数据存储，但它的速度慢，而且不能处理二进制数据。IndexedDB 和 WebSQL 是异步的，速度快，支持大数据集，但他们的API 使用起来有点复杂。不仅如此，IndexedDB 和 WebSQL 没有被所有的主流的浏览器厂商支持，这种情况最近也不太可能改变。</p> <p>Mozilla 开发了一个叫 localForage 的库 ，使得离线数据存储在任何浏览器都是一项容易的任务。</p> <p>localForage 是一个使用非常简单的 JavaScript 库的，提供了 get，set，remove，clear 和 length 等等 API，还具有以下特点：</p> <p>支持回调的异步 API；</p> <ul><li>支持 IndexedDB，WebSQL 和 localStorage 三种存储模式（自动为你加载最佳的驱动程序）；</li> <li>支持 BLOB 和任意类型的数据，让您可以存储图片，文件等等。</li> <li>支持 ES6 Promises；</li></ul> <p>对 IndexedDB 和 WebSQL 的支持使您可以为您的 Web 应用程序存储更多的数据，要比 localStorage 允许存储的多很多。其 API 的无阻塞性质使得您的应用程序更快，不会因为 Get/Set 调用而挂起主线程。</p> <div class="language-sh extra-class"><pre class="language-sh"><code><span class="token function">npm</span> <span class="token function">install</span> localforage -S
</code></pre></div><p>src/api/home.js</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">export</span> <span class="token keyword">function</span> <span class="token function">download</span><span class="token punctuation">(</span><span class="token parameter">book<span class="token punctuation">,</span> onSucess<span class="token punctuation">,</span> onError<span class="token punctuation">,</span> onProgress</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>onProgress <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    onProgress <span class="token operator">=</span> onError
    onError <span class="token operator">=</span> <span class="token keyword">null</span>
  <span class="token punctuation">}</span>
  <span class="token keyword">return</span> axios<span class="token punctuation">.</span><span class="token function">create</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
    baseURL<span class="token operator">:</span> process<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">VUE_APP_EPUB_URL</span><span class="token punctuation">,</span>
    method<span class="token operator">:</span> <span class="token string">'get'</span><span class="token punctuation">,</span>
    responseType<span class="token operator">:</span> <span class="token string">'blob'</span><span class="token punctuation">,</span>
    timeout<span class="token operator">:</span> <span class="token number">180</span> <span class="token operator">*</span> <span class="token number">1000</span><span class="token punctuation">,</span>
    <span class="token comment">// 下载进度</span>
    <span class="token function-variable function">onDownloadProgress</span><span class="token operator">:</span> <span class="token parameter">progressEvent</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
      <span class="token keyword">if</span> <span class="token punctuation">(</span>onProgress<span class="token punctuation">)</span> <span class="token function">onProgress</span><span class="token punctuation">(</span>progressEvent<span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>book<span class="token punctuation">.</span>categoryText<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">/</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>book<span class="token punctuation">.</span>fileName<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">.epub</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">res</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
      <span class="token keyword">const</span> blob <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Blob</span><span class="token punctuation">(</span><span class="token punctuation">[</span>res<span class="token punctuation">.</span>data<span class="token punctuation">]</span><span class="token punctuation">)</span>
      <span class="token function">setLocalForage</span><span class="token punctuation">(</span>book<span class="token punctuation">.</span>fileName<span class="token punctuation">,</span> blob<span class="token punctuation">,</span>
        <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token function">onSucess</span><span class="token punctuation">(</span>book<span class="token punctuation">)</span><span class="token punctuation">,</span>
        <span class="token parameter">err</span> <span class="token operator">=&gt;</span> <span class="token function">onError</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">catch</span><span class="token punctuation">(</span><span class="token parameter">err</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
      <span class="token keyword">if</span> <span class="token punctuation">(</span>onError<span class="token punctuation">)</span> <span class="token function">onError</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre></div><p>src/components/shelf/ShelfFooter.vue</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">async</span> <span class="token function">downloadSelectedBook</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">let</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> <span class="token keyword">this</span><span class="token punctuation">.</span>shelfSelected<span class="token punctuation">.</span>length<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">await</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">downloadBook</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>shelfSelected<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span>
      <span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">book</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
        book<span class="token punctuation">.</span>cache <span class="token operator">=</span> <span class="token boolean">true</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token function">downloadBook</span><span class="token punctuation">(</span><span class="token parameter">book</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">let</span> text <span class="token operator">=</span> <span class="token string">''</span>
  <span class="token keyword">const</span> toast <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">toast</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
    text
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
  toast<span class="token punctuation">.</span><span class="token function">continueShow</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Promise</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">resolve<span class="token punctuation">,</span> reject</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token function">download</span><span class="token punctuation">(</span>book<span class="token punctuation">,</span> <span class="token parameter">book</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
      toast<span class="token punctuation">.</span><span class="token function">remove</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
      <span class="token function">resolve</span><span class="token punctuation">(</span>book<span class="token punctuation">)</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span> reject<span class="token punctuation">,</span> <span class="token parameter">progressEvent</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
      <span class="token keyword">const</span> progress <span class="token operator">=</span> Math<span class="token punctuation">.</span><span class="token function">floor</span><span class="token punctuation">(</span>progressEvent<span class="token punctuation">.</span>loaded <span class="token operator">/</span> progressEvent<span class="token punctuation">.</span>total <span class="token operator">*</span> <span class="token number">100</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token string">'%'</span>
      text <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">$t</span><span class="token punctuation">(</span><span class="token string">'shelf.progressDownload'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token string">'$1'</span><span class="token punctuation">,</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>book<span class="token punctuation">.</span>fileName<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">.epub(</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>progress<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">)</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span>
      toast<span class="token punctuation">.</span><span class="token function">updateText</span><span class="token punctuation">(</span>text<span class="token punctuation">)</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre></div><p><a href="https://www.cnblogs.com/lhb25/p/localforage-offline-storage-improved.html" target="_blank" rel="noopener noreferrer">localForage——轻松实现 Web 离线存储<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></p> <h2 id="电子书缓存删除功能开发"><a href="#电子书缓存删除功能开发" class="header-anchor">#</a> 电子书缓存删除功能开发</h2> <div class="language-js extra-class"><pre class="language-js"><code><span class="token function">removeSelectedBook</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  Promise<span class="token punctuation">.</span><span class="token function">all</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>shelfSelected<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token parameter">book</span> <span class="token operator">=&gt;</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">removeBook</span><span class="token punctuation">(</span>book<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">books</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
      books<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token parameter">book</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
        book<span class="token punctuation">.</span>cache <span class="token operator">=</span> <span class="token boolean">false</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span>
      <span class="token function">saveBookShelf</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>shelfList<span class="token punctuation">)</span>
      <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">simpleToast</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">$t</span><span class="token punctuation">(</span><span class="token string">'shelf.removeDownloadSuccess'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token function">removeBook</span><span class="token punctuation">(</span><span class="token parameter">book</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Promise</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">resolve<span class="token punctuation">,</span> reject</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token function">removeLocalStorage</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>book<span class="token punctuation">.</span>category<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">/</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>book<span class="token punctuation">.</span>file_name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">-book-info</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span>
    <span class="token function">removeLocalForage</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>book<span class="token punctuation">.</span>file_name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span>
    <span class="token function">resolve</span><span class="token punctuation">(</span>book<span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre></div><p>http://192.168.0.102:8083/epub2/%E5%8C%BA%E5%9D%97%E9%93%BE%E5%B0%86%E5%A6%82%E4%BD%95%E9%87%8D%E6%96%B0%E5%AE%9A%E4%B9%89%E4%B8%96%E7%95%8C/OEBPS/package.opf
http://192.168.0.102:8083/epub2/2016_Book_AgileProcessesInSoftwareEngine/OEBPS/package.opf</p> <h2 id="书架缓存-离线阅读功能开发"><a href="#书架缓存-离线阅读功能开发" class="header-anchor">#</a> 书架缓存+离线阅读功能开发</h2> <p>书架缓存</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token function">getShelfList</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">let</span> shelfList <span class="token operator">=</span> <span class="token function">getBookShelf</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  
  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>shelfList <span class="token operator">||</span> <span class="token operator">!</span><span class="token punctuation">(</span>shelfList<span class="token operator">+</span><span class="token string">''</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token function">shelf</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">response</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
      <span class="token keyword">if</span> <span class="token punctuation">(</span>response<span class="token punctuation">.</span>status <span class="token operator">===</span> <span class="token number">200</span> <span class="token operator">&amp;&amp;</span> response<span class="token punctuation">.</span>data <span class="token operator">&amp;&amp;</span> response<span class="token punctuation">.</span>data<span class="token punctuation">.</span>bookList<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        shelfList <span class="token operator">=</span> <span class="token function">appendAddToShelf</span><span class="token punctuation">(</span>response<span class="token punctuation">.</span>data<span class="token punctuation">.</span>bookList<span class="token punctuation">)</span>
        <span class="token function">saveBookShelf</span><span class="token punctuation">(</span>shelfList<span class="token punctuation">)</span>
        <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setShelfList</span><span class="token punctuation">(</span>shelfList<span class="token punctuation">)</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setShelfList</span><span class="token punctuation">(</span>shelfList<span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><p>离线阅读</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token function">mounted</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> books <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>$route<span class="token punctuation">.</span>params<span class="token punctuation">.</span>fileName<span class="token punctuation">.</span><span class="token function">split</span><span class="token punctuation">(</span><span class="token string">&quot;|&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> fileName <span class="token operator">=</span> books<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
  <span class="token function">getLocalForage</span><span class="token punctuation">(</span>fileName<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> blob</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>err <span class="token operator">&amp;&amp;</span> blob<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setFileName</span><span class="token punctuation">(</span>books<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">&quot;/&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">initEpub</span><span class="token punctuation">(</span>blob<span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
      <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setFileName</span><span class="token punctuation">(</span>books<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">&quot;/&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
        <span class="token keyword">const</span> url <span class="token operator">=</span>
          process<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">VUE_APP_BASE_URL</span> <span class="token operator">+</span> <span class="token string">&quot;/epub/&quot;</span> <span class="token operator">+</span> <span class="token keyword">this</span><span class="token punctuation">.</span>fileName <span class="token operator">+</span> <span class="token string">&quot;.epub&quot;</span><span class="token punctuation">;</span>

        <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">initEpub</span><span class="token punctuation">(</span>url<span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><h2 id="书架分组功能开发"><a href="#书架分组功能开发" class="header-anchor">#</a> 书架分组功能开发</h2> <p>移动分组</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token function">moveToGroup</span><span class="token punctuation">(</span><span class="token parameter">group</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setShelfList</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>shelfList
    <span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token parameter">book</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
      <span class="token keyword">if</span> <span class="token punctuation">(</span>book<span class="token punctuation">.</span>itemList<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        book<span class="token punctuation">.</span>itemList <span class="token operator">=</span> book<span class="token punctuation">.</span>itemList<span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token parameter">subBook</span> <span class="token operator">=&gt;</span> <span class="token keyword">this</span><span class="token punctuation">.</span>shelfSelected<span class="token punctuation">.</span><span class="token function">indexOf</span><span class="token punctuation">(</span>subBook<span class="token punctuation">)</span> <span class="token operator">&lt;</span> <span class="token number">0</span><span class="token punctuation">)</span>
      <span class="token punctuation">}</span>
      <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>shelfSelected<span class="token punctuation">.</span><span class="token function">indexOf</span><span class="token punctuation">(</span>book<span class="token punctuation">)</span> <span class="token operator">&lt;</span> <span class="token number">0</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
      <span class="token keyword">if</span> <span class="token punctuation">(</span>group <span class="token operator">&amp;&amp;</span> group<span class="token punctuation">.</span>itemList<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        group<span class="token punctuation">.</span>itemList <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token operator">...</span>group<span class="token punctuation">.</span>itemList<span class="token punctuation">,</span> <span class="token operator">...</span><span class="token keyword">this</span><span class="token punctuation">.</span>shelfSelected<span class="token punctuation">]</span>
        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>group<span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span>
      group<span class="token punctuation">.</span>itemList<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">item<span class="token punctuation">,</span> index</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
        item<span class="token punctuation">.</span>id <span class="token operator">=</span> index <span class="token operator">+</span> <span class="token number">1</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span>
      <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">simpleToast</span><span class="token punctuation">(</span><span class="token string">'成功移入'</span> <span class="token operator">+</span> group<span class="token punctuation">.</span>title<span class="token punctuation">)</span>
      <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">onComplete</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre></div><p>新建分组</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token function">createNewGroup</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token keyword">this</span><span class="token punctuation">.</span>newGroupName <span class="token operator">||</span> <span class="token keyword">this</span><span class="token punctuation">.</span>newGroupName<span class="token punctuation">.</span>length <span class="token operator">===</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span>
  <span class="token punctuation">}</span>
  <span class="token comment">// 分组名的修改</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>showNewGroup<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>shelfCategory<span class="token punctuation">.</span>title <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>newGroupName
    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">onComplete</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
    <span class="token comment">// 新增分组</span>
    <span class="token keyword">const</span> group <span class="token operator">=</span> <span class="token punctuation">{</span>
      id<span class="token operator">:</span> <span class="token keyword">this</span><span class="token punctuation">.</span>shelfList<span class="token punctuation">[</span><span class="token keyword">this</span><span class="token punctuation">.</span>shelfList<span class="token punctuation">.</span>length <span class="token operator">-</span> <span class="token number">2</span><span class="token punctuation">]</span><span class="token punctuation">.</span>id <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">,</span>
      itemList<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
      selected<span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span>
      title<span class="token operator">:</span> <span class="token keyword">this</span><span class="token punctuation">.</span>newGroupName<span class="token punctuation">,</span>
      type<span class="token operator">:</span> <span class="token number">2</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">let</span> list <span class="token operator">=</span> <span class="token function">removeAddFromShelf</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>shelfList<span class="token punctuation">)</span>
    list<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>group<span class="token punctuation">)</span>
    list <span class="token operator">=</span> <span class="token function">appendAddToShelf</span><span class="token punctuation">(</span>list<span class="token punctuation">)</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setShelfList</span><span class="token punctuation">(</span>list<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
      <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">moveToGroup</span><span class="token punctuation">(</span>group<span class="token punctuation">)</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
</code></pre></div><h2 id="书架列表过渡动画开发"><a href="#书架列表过渡动画开发" class="header-anchor">#</a> 书架列表过渡动画开发</h2> <h2 id="书架分类列表开发"><a href="#书架分类列表开发" class="header-anchor">#</a> 书架分类列表开发</h2> <div class="language-js extra-class"><pre class="language-js"><code><span class="token function">getCategoryList</span> <span class="token punctuation">(</span><span class="token parameter">title</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">getShelfList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token comment">// type为1显示图书 type为2显示的是分组</span>
    <span class="token keyword">const</span> categoryList <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>shelfList<span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token parameter">book</span> <span class="token operator">=&gt;</span> book<span class="token punctuation">.</span>type <span class="token operator">===</span> <span class="token number">2</span> <span class="token operator">&amp;&amp;</span> book<span class="token punctuation">.</span>title <span class="token operator">===</span> title<span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setShelfCategory</span><span class="token punctuation">(</span>categoryList<span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre></div><h2 id="书架分组功能优化"><a href="#书架分组功能优化" class="header-anchor">#</a> 书架分组功能优化</h2> <p>移除分组</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">export</span> <span class="token keyword">function</span> <span class="token function">computeId</span> <span class="token punctuation">(</span><span class="token parameter">list</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> list<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">book<span class="token punctuation">,</span> index</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>book<span class="token punctuation">.</span>type <span class="token operator">!==</span> <span class="token number">3</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      book<span class="token punctuation">.</span>id <span class="token operator">=</span> index <span class="token operator">+</span> <span class="token number">1</span>
      <span class="token keyword">if</span> <span class="token punctuation">(</span>book<span class="token punctuation">.</span>itemList<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        book<span class="token punctuation">.</span>itemList <span class="token operator">=</span> <span class="token function">computeId</span><span class="token punctuation">(</span>book<span class="token punctuation">.</span>itemList<span class="token punctuation">)</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">return</span> book
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token function">moveOutOfGroup</span> <span class="token punctuation">(</span><span class="token parameter">f</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setShelfList</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>shelfList<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token parameter">book</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token comment">// type 为 2 代表分组</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>book<span class="token punctuation">.</span>type <span class="token operator">===</span> <span class="token number">2</span> <span class="token operator">&amp;&amp;</span> book<span class="token punctuation">.</span>itemList<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token comment">// 保留没有被选中的图书</span>
      book<span class="token punctuation">.</span>itemList <span class="token operator">=</span> book<span class="token punctuation">.</span>itemList<span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token parameter">subBook</span> <span class="token operator">=&gt;</span> <span class="token operator">!</span>subBook<span class="token punctuation">.</span>selected<span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">return</span> book
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token comment">// 将选中的电子书添加的书架的最后</span>
    <span class="token comment">// removeAddFromShelf 移除加号</span>
    <span class="token comment">// appendAddToShelf 添加加号</span>
    <span class="token keyword">const</span> list <span class="token operator">=</span> <span class="token function">computeId</span><span class="token punctuation">(</span><span class="token function">appendAddToShelf</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">concat</span><span class="token punctuation">(</span>
      <span class="token function">removeAddFromShelf</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>shelfList<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token operator">...</span><span class="token keyword">this</span><span class="token punctuation">.</span>shelfSelected<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setShelfList</span><span class="token punctuation">(</span>list<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
      <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">simpleToast</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">$t</span><span class="token punctuation">(</span><span class="token string">'shelf.moveBookOutSuccess'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
      <span class="token keyword">if</span> <span class="token punctuation">(</span>f<span class="token punctuation">)</span> <span class="token function">f</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre></div><h2 id="书架修改分组功能开发"><a href="#书架修改分组功能开发" class="header-anchor">#</a> 书架修改分组功能开发</h2> <div class="language-js extra-class"><pre class="language-js"><code><span class="token function">changeGroupName</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">hidePopup</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">dialog</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
    showNewGroup<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
    groupName<span class="token operator">:</span> <span class="token keyword">this</span><span class="token punctuation">.</span>shelfCategory<span class="token punctuation">.</span>title
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">show</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token function">deleteGroup</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token keyword">this</span><span class="token punctuation">.</span>emptyCategory<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setShelfSelected</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>shelfCategory<span class="token punctuation">.</span>itemList<span class="token punctuation">)</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">moveOutOfGroup</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>onComplete<span class="token punctuation">)</span>
  <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">onComplete</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token function">showDeleteGroup</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">hidePopup</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>popupMenu <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">popup</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
      title<span class="token operator">:</span> <span class="token string">'确定删除该分组吗？'</span><span class="token punctuation">,</span>
      btn<span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">createPopupBtn</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">$t</span><span class="token punctuation">(</span><span class="token string">'shelf.confirm'</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
          <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">deleteGroup</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token string">'danger'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>popupCancelBtn
      <span class="token punctuation">]</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">show</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token number">200</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token function">changeGroup</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span>popupMenu <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">popup</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
    btn<span class="token operator">:</span> <span class="token punctuation">[</span>
      <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">createPopupBtn</span><span class="token punctuation">(</span><span class="token string">'修改分组名'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">changeGroupName</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
      <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">createPopupBtn</span><span class="token punctuation">(</span><span class="token string">'删除分组'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">showDeleteGroup</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span>
    <span class="token punctuation">]</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">show</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre></div><h2 id="vue项目构建"><a href="#vue项目构建" class="header-anchor">#</a> Vue项目构建</h2> <h2 id="功能优化-构建问题处理"><a href="#功能优化-构建问题处理" class="header-anchor">#</a> 功能优化+构建问题处理</h2> <h2 id="数据库环境准备"><a href="#数据库环境准备" class="header-anchor">#</a> 数据库环境准备</h2> <h2 id="node-js-express编写api"><a href="#node-js-express编写api" class="header-anchor">#</a> Node.js+express编写API</h2> <h2 id="书城首页api开发"><a href="#书城首页api开发" class="header-anchor">#</a> 书城首页API开发</h2> <h2 id="书城首页api开发-2"><a href="#书城首页api开发-2" class="header-anchor">#</a> 书城首页API开发</h2> <h2 id="书城首页前后端api联调-解决cors跨域"><a href="#书城首页前后端api联调-解决cors跨域" class="header-anchor">#</a> 书城首页前后端API联调（解决CORS跨域）</h2> <h2 id="电子书详情api开发"><a href="#电子书详情api开发" class="header-anchor">#</a> 电子书详情API开发</h2> <h2 id="电子书列表api开发"><a href="#电子书列表api开发" class="header-anchor">#</a> 电子书列表API开发</h2> <h2 id="后端api源码上传git演示"><a href="#后端api源码上传git演示" class="header-anchor">#</a> 后端API源码上传git演示</h2> <h2 id="阿里云ecs服务器开通"><a href="#阿里云ecs服务器开通" class="header-anchor">#</a> 阿里云ECS服务器开通</h2> <p><a href="https://www.aliyun.com/product/ecs?spm=5176.19720258.J_8058803260.89.7b812c4aEZvbzk" target="_blank" rel="noopener noreferrer">阿里云官网<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></p> <p>服务器的配置最好从低到高，如果从高到低配置会比较麻烦。</p> <p>连接</p> <div class="language-sh extra-class"><pre class="language-sh"><code><span class="token function">ssh</span> root@47.93.173.132
</code></pre></div><div class="language-sh extra-class"><pre class="language-sh"><code><span class="token function">who</span>
</code></pre></div><h3 id="配置免密登录"><a href="#配置免密登录" class="header-anchor">#</a> 配置免密登录</h3> <p>生成 SSH 公钥</p> <div class="language-sh extra-class"><pre class="language-sh"><code>ssh-keygen -t rsa
</code></pre></div><div class="language-sh extra-class"><pre class="language-sh"><code>ssh-copy-id -i ~/.ssh/id_rsa.pub root@47.93.173.132
</code></pre></div><div class="language-sh extra-class"><pre class="language-sh"><code><span class="token function">ssh</span> root@47.93.173.132
</code></pre></div><p>还可以修改 host 文件</p> <div class="language- extra-class"><pre class="language-text"><code>47.93.173.132 ebook
</code></pre></div><div class="language- extra-class"><pre class="language-text"><code>ping ebook
</code></pre></div><div class="language-sh extra-class"><pre class="language-sh"><code><span class="token function">ssh</span> root@ebook
</code></pre></div><h3 id="保持和远程服务器连接"><a href="#保持和远程服务器连接" class="header-anchor">#</a> 保持和远程服务器连接</h3> <p>长时间不操作，终端会输出 <code>Broken pipe</code> ，表示 SSH 连接被服务器断开了。</p> <p>查看 SSH 配置文件</p> <div class="language-sh extra-class"><pre class="language-sh"><code><span class="token function">vim</span> /etc/ssh/sshd_config
</code></pre></div><p>修改完配置文件后要重启</p> <div class="language-sh extra-class"><pre class="language-sh"><code><span class="token function">service</span> sshd restart
</code></pre></div><p>or</p> <div class="language-sh extra-class"><pre class="language-sh"><code><span class="token function">sudo</span> launchctl stop com.openssh.sshd
<span class="token function">sudo</span> launchctl start com.openssh.sshd
</code></pre></div><p><a href="https://blog.csdn.net/oblily/article/details/88055196" target="_blank" rel="noopener noreferrer">SSH - 防止自动接续切断<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></p> <p><a href="https://blog.csdn.net/xieyi2015/article/details/70990922" target="_blank" rel="noopener noreferrer">ssh_config和sshd_config配置文件<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>
断开远程服务连接</p> <div class="language-sh extra-class"><pre class="language-sh"><code><span class="token builtin class-name">exit</span>
</code></pre></div><h2 id="centos-node-js环境搭建"><a href="#centos-node-js环境搭建" class="header-anchor">#</a> CentOS Node.js环境搭建</h2> <div class="language-sh extra-class"><pre class="language-sh"><code><span class="token function">wget</span> -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh <span class="token operator">|</span> <span class="token function">bash</span>
</code></pre></div><p>查看安装结果</p> <div class="language-sh extra-class"><pre class="language-sh"><code>ll .nvm/
</code></pre></div><div class="language-sh extra-class"><pre class="language-sh"><code>ll .bash
ll .bash_profile
<span class="token function">vim</span> .bash_profile

<span class="token function">vim</span> .bashrc
<span class="token comment"># 安装 node ，这样默认安装的是最新版本，可能会不稳定</span>
nvm <span class="token function">install</span> node
</code></pre></div><div class="language-sh extra-class"><pre class="language-sh"><code><span class="token comment"># 指定安装 12.17.0 版本</span>
nvm <span class="token function">install</span> <span class="token number">10.24</span>.1
</code></pre></div><p><a href="https://copyfuture.com/blogs-details/20200526220158733w8fvk9tfjpj7o0y" target="_blank" rel="noopener noreferrer">centos升级node版本<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></p> <p>服务器安装 cnpm</p> <div class="language-sh extra-class"><pre class="language-sh"><code><span class="token function">npm</span> <span class="token function">install</span> cnpm -g --registry<span class="token operator">=</span>https://registry.npm.taobao.org
</code></pre></div><p><a href="https://blog.csdn.net/weixin_42467467/article/details/105423801" target="_blank" rel="noopener noreferrer">阿里云CentOs搭建node环境以及配置API接口服务器<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></p> <h2 id="centos-ngnix环境搭建"><a href="#centos-ngnix环境搭建" class="header-anchor">#</a> CentOS Ngnix环境搭建</h2> <div class="language-sh extra-class"><pre class="language-sh"><code>yum -y <span class="token function">install</span> pcre*
</code></pre></div><div class="language-sh extra-class"><pre class="language-sh"><code>yum -y <span class="token function">install</span> openssl*
</code></pre></div><div class="language-sh extra-class"><pre class="language-sh"><code>ll
<span class="token comment"># 新建一个目录，将nginx包放到这里</span>
<span class="token function">mkdir</span> nginx
ll
<span class="token builtin class-name">cd</span> nginx
```sh
<span class="token function">wget</span> http://nginx.org/download/nginx-1.18.0.tar.gz
<span class="token comment"># 解压</span>
<span class="token function">tar</span> -zxvf nginx-1.18.0.tar.gz
</code></pre></div><p>相当于创建了一个快捷方式</p> <p>bin目录下的指令都是写好的，
cd 到bin目录，执行</p> <div class="language-sh extra-class"><pre class="language-sh"><code><span class="token function">ln</span> -s /usr/local/nginx/sbin/nginx nginx
</code></pre></div><p>执行</p> <div class="language-sh extra-class"><pre class="language-sh"><code>ll
</code></pre></div><p>打印输出</p> <p>lrwxrwxrwx 1 root root 27 5月  16 09:14 nginx -&gt; /usr/local/nginx/sbin/nginx</p> <p>然后回到root</p> <div class="language-sh extra-class"><pre class="language-sh"><code><span class="token builtin class-name">cd</span>
</code></pre></div><p>关闭 nginx</p> <div class="language-sh extra-class"><pre class="language-sh"><code>nginx -s stop
</code></pre></div><p>因为目前用户是root，已经拿到了最高权限，所以不用加 sudo 。</p> <div class="language-sh extra-class"><pre class="language-sh"><code><span class="token builtin class-name">cd</span> /usr/local/nginx
ll
<span class="token builtin class-name">cd</span> /conf
<span class="token function">vim</span> nginx.conf
</code></pre></div><p>根目录</p> <div class="language-sh extra-class"><pre class="language-sh"><code>ll
<span class="token comment"># 这个nginx是我们上面创建的文件夹</span>
<span class="token builtin class-name">cd</span> nginx
<span class="token comment"># 创建nginx配置文件</span>
<span class="token function">vim</span> nginx.conf
</code></pre></div><p>配置此 nginx.conf 配置文件</p> <div class="language- extra-class"><pre class="language-text"><code>server {
  listen 80;
  server_name local_host;
  root /root/nginx/upload;
  # 测试完成后，线上不建议打开这个选项
  #autoindex on;
  add_header Cache-Control &quot;no-cache, must-revalidate&quot;;
  location / {
    add_header Access-Control-Allow-Origin *;
  }
}
</code></pre></div><p>修改 nginx 主配置文件</p> <div class="language-sh extra-class"><pre class="language-sh"><code>user root<span class="token punctuation">;</span>

include /root/nginx/*.conf
</code></pre></div><p>在 nginx 文件夹中新建 upload 文件</p> <div class="language-sh extra-class"><pre class="language-sh"><code><span class="token comment"># 检查配置文件</span>
nginx -t
</code></pre></div><p>尝试访问，浏览器输入<code>http://39.107.75.46/cover/bio/2016_Book_ATimeForMetabolismAndHormones.jpeg</code></p> <p><a href="https://www.filezilla.cn/" target="_blank" rel="noopener noreferrer">FileZilla下载地址<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></p> <p><a href="https://blog.csdn.net/feng2147685/article/details/106012829/" target="_blank" rel="noopener noreferrer">nginx启动时报错nginx: [error] open() &quot;/usr/local/nginx/logs/nginx.pid&quot; failed (2: No such file or directory)，进入到logs目录发现确实没有nginx.pid文件<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></p> <p><a href="https://blog.csdn.net/JiaEnYa/article/details/89950773" target="_blank" rel="noopener noreferrer">【涂叶node】CentOS 通过npm 全局安装pm2后，mac上出现 pm2 未找到命令（commend not found）解决方案<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></p> <div class="language-sh extra-class"><pre class="language-sh"><code><span class="token function">whereis</span> pm2
</code></pre></div><p>输出</p> <div class="language- extra-class"><pre class="language-text"><code>/opt/node-v12.18.1-linux-x64/bin/pm2
</code></pre></div><div class="language-sh extra-class"><pre class="language-sh"><code><span class="token function">ln</span> -s /opt/node-v12.18.1-linux-x64/bin/pm2 /usr/local/bin
</code></pre></div><h2 id="centos-git部署-免密更新"><a href="#centos-git部署-免密更新" class="header-anchor">#</a> CentOS git部署+免密更新</h2> <div class="language-sh extra-class"><pre class="language-sh"><code>yum <span class="token function">install</span> -y <span class="token function">git</span>
</code></pre></div><p>查看安装的 git 版本</p> <div class="language-sh extra-class"><pre class="language-sh"><code><span class="token function">git</span> version
</code></pre></div><p>删除 yum 源上的git</p> <div class="language-sh extra-class"><pre class="language-sh"><code>yum remove <span class="token function">git</span>
</code></pre></div><p>生成 git 秘钥</p> <div class="language-sh extra-class"><pre class="language-sh"><code>ssh-keygen -t rsa -C <span class="token string">&quot;你 git 账户&quot;</span>
</code></pre></div><p>打印秘钥</p> <div class="language-sh extra-class"><pre class="language-sh"><code><span class="token function">cat</span> ~/.ssh/id_rsa.pub
</code></pre></div><p>在 git 的用户设置中点击添加秘钥，把这个秘钥添加上去。</p> <h2 id="centos-前端项目构建和发布"><a href="#centos-前端项目构建和发布" class="header-anchor">#</a> CentOS 前端项目构建和发布</h2> <h2 id="centos-mysql环境安装"><a href="#centos-mysql环境安装" class="header-anchor">#</a> CentOS MySQL环境安装</h2> <div class="language-sh extra-class"><pre class="language-sh"><code>yum -y <span class="token function">install</span> mysql-server
</code></pre></div><p>默认密码：yp*koEu2&amp;eet</p> <p>登录成功后</p> <div class="language-sh extra-class"><pre class="language-sh"><code>show databases<span class="token punctuation">;</span>
</code></pre></div><p>会报</p> <div class="language- extra-class"><pre class="language-text"><code>ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executing this statement.
</code></pre></div><p>设置密码：</p> <div class="language-sh extra-class"><pre class="language-sh"><code>alter user <span class="token string">'root'</span>@<span class="token string">'localhost'</span> identified  by <span class="token string">'bf628g?@'</span><span class="token punctuation">;</span>
</code></pre></div><p><a href="https://ecs.console.aliyun.com/?spm=5176.12901015.0.i12901015.3149525c3rO18o#/securityGroupDetail/region/cn-beijing/groupId/sg-2zebr70gcdc5f9qehw3w/detail/intranetIngress" target="_blank" rel="noopener noreferrer">设置安全组<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></p> <div class="language-sh extra-class"><pre class="language-sh"><code>use mysql<span class="token punctuation">;</span>
create user <span class="token string">'root'</span>@<span class="token string">'%'</span> identified with mysql_native_password by <span class="token string">'bf628g?@'</span><span class="token punctuation">;</span>
</code></pre></div><p>只有一个数据库
<a href=""></a>
这种情况是因为权限还没有赋予</p> <div class="language-sh extra-class"><pre class="language-sh"><code>grant all privileges on *.* to <span class="token string">'root'</span>@<span class="token string">'%'</span><span class="token punctuation">;</span>
</code></pre></div><p>使权限生效</p> <div class="language-sh extra-class"><pre class="language-sh"><code>flush privileges<span class="token punctuation">;</span>
</code></pre></div><p>关闭连接，再连接，可以看到四个库都有了
<a href=""></a></p> <p>新建一个book库</p> <p>在查询右键单击选择新建查询，将sql语句复制进去，执行即可</p> <div class="language-sh extra-class"><pre class="language-sh"><code>use book<span class="token punctuation">;</span>
</code></pre></div><div class="language-sh extra-class"><pre class="language-sh"><code>show tables<span class="token punctuation">;</span>
</code></pre></div><div class="language- extra-class"><pre class="language-text"><code>不要执行
```sh
rm -rf /usr/lib64/mysql
rm -rf /usr/share/mysql
</code></pre></div><p><a href="https://blog.csdn.net/qq_25992179/article/details/82909310" target="_blank" rel="noopener noreferrer">LInux Mysql 启动时报错： Job for mysqld.service failed because the control process exited with err...解决方法<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></p> <p><a href="https://www.cnblogs.com/lan-blue/p/14176075.html" target="_blank" rel="noopener noreferrer">centos8中的MySQL卸载和安装<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></p> <p><a href="https://blog.csdn.net/haogexiaole/article/details/88584032" target="_blank" rel="noopener noreferrer">Mysql在linux上执行命令未找到，设置软链接到/usr/bin目录中<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></p> <p><a href="https://www.cnblogs.com/_error/p/13226502.html" target="_blank" rel="noopener noreferrer">CentOS8 安装MySQL8（ECS系列二）<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></p> <p><a href="https://www.bilibili.com/video/av243446971/" target="_blank" rel="noopener noreferrer">Arduino ESP32+ESP8266库快速安装 for MAC Win10（离线包更快<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></p> <h2 id="centos-一键部署脚本开发"><a href="#centos-一键部署脚本开发" class="header-anchor">#</a> CentOS 一键部署脚本开发</h2> <h2 id="阿里云域名注册、解析与备案流程"><a href="#阿里云域名注册、解析与备案流程" class="header-anchor">#</a> 阿里云域名注册、解析与备案流程</h2> <h2 id="升级centos到8-0的错误处理"><a href="#升级centos到8-0的错误处理" class="header-anchor">#</a> 升级centos到8.0的错误处理</h2> <ol><li>Please contact your system administrator. Add correct host key in /Users/wangzhihao/.ssh/known_hosts</li></ol> <p><img src="/assets/img/11.deb55c5b.png" alt=""></p> <div class="language-sh extra-class"><pre class="language-sh"><code>ssh-keygen -R <span class="token number">47.93</span>.173.132
</code></pre></div><p>https://blog.csdn.net/zt15732625878/article/details/97523429</p> <p>目前用到的数组方法</p> <div class="language- extra-class"><pre class="language-text"><code>some
filter

</code></pre></div><p>测试题：</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">Myfn</span><span class="token punctuation">(</span><span class="token parameter">name</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token class-name">Myfn</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span>name <span class="token operator">=</span> name
    <span class="token keyword">return</span> <span class="token class-name">Myfn</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function">init</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token class-name">Myfn</span><span class="token punctuation">.</span>prototype <span class="token operator">=</span> <span class="token punctuation">{</span>
    task<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token function">init</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token keyword">this</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token function">play</span><span class="token punctuation">(</span><span class="token parameter">p</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>name<span class="token operator">+</span><span class="token string">'玩'</span><span class="token operator">+</span>p<span class="token punctuation">)</span>
        <span class="token keyword">return</span> <span class="token keyword">this</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token function">eat</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">let</span> <span class="token function-variable function">fn</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
            console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'吃饭'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>task<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>fn<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
        <span class="token keyword">return</span> <span class="token keyword">this</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token function">sleep</span><span class="token punctuation">(</span><span class="token parameter">timer</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
       <span class="token keyword">this</span><span class="token punctuation">.</span>task<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">=&gt;</span><span class="token punctuation">{</span>
           <span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
               <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
           <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token number">1000</span><span class="token operator">*</span>timer<span class="token punctuation">)</span>
       <span class="token punctuation">}</span><span class="token punctuation">)</span>
       <span class="token keyword">return</span> <span class="token keyword">this</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">const</span> fn <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>task<span class="token punctuation">.</span><span class="token function">shift</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
        fn <span class="token operator">&amp;&amp;</span> <span class="token function">fn</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token function">Myfn</span><span class="token punctuation">(</span><span class="token string">'张三'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">play</span><span class="token punctuation">(</span><span class="token string">'足球'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">play</span><span class="token punctuation">(</span><span class="token string">'篮球'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">sleep</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">eat</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

</code></pre></div><p>vue.js 进行初始化遇到的关于core-js的错误@core-js/modules/es6.array.find-index (ERROR Failed to compile with 164 errors These dependencies were not found)</p> <p>原因是 core-js版本太高</p> <div class="language-sh extra-class"><pre class="language-sh"><code>cnpm <span class="token function">install</span> core-js@2
</code></pre></div><h2 id="路由"><a href="#路由" class="header-anchor">#</a> 路由</h2> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// detail</span>
<span class="token function">showBookDetail</span> <span class="token punctuation">(</span><span class="token parameter">book</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> <span class="token punctuation">{</span> file_name<span class="token punctuation">,</span> category<span class="token punctuation">,</span> id <span class="token punctuation">}</span> <span class="token operator">=</span> book
  <span class="token keyword">this</span><span class="token punctuation">.</span>$router<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
    path<span class="token operator">:</span> <span class="token string">'/store/detail'</span><span class="token punctuation">,</span>
    query<span class="token operator">:</span> <span class="token punctuation">{</span>
      id<span class="token punctuation">,</span>
      category<span class="token punctuation">,</span>
      fileName<span class="token operator">:</span> file_name
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token comment">// router.js</span>
<span class="token punctuation">{</span>
  path<span class="token operator">:</span> <span class="token string">'detail'</span><span class="token punctuation">,</span>
  <span class="token function-variable function">component</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token keyword">import</span><span class="token punctuation">(</span><span class="token string">'../views/store/StoreDetail.vue'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre></div><p>项目难点：</p> <p>阅读器开发：</p> <p>分页算法，需要给电子书分出页面，难点是因为每个阅读器的屏幕尺寸可能是不一样的，所以分出来的页数也是不一样的</p> <p>全文搜索算法 在当前书籍中实现全文搜索，并快速定位到搜索的位置</p> <p>引入web字体</p> <p>主题设计：主题一旦变化，阅读器的背景、文字颜色等都要发生变化</p> <p>离线存储机制设计：localstorage+indexedDB对书籍进行缓存实现离线阅读</p> <p>实现复杂手势和交互动画，如何兼容手势和鼠标操作</p> <p>利用vuex+minx机制实现组件解耦+复用，精简代码量</p> <p>利用es6优雅的实现数据结构变化</p></div> <footer class="page-edit"><!----> <!----></footer> <!----> </main></div><div class="global-ui"><!----><!----></div></div>
    <script src="/assets/js/app.8c5a7a92.js" defer></script><script src="/assets/js/2.8e30e130.js" defer></script><script src="/assets/js/10.e695640a.js" defer></script><script src="/assets/js/64.0323ed89.js" defer></script>
  </body>
</html>
